Come posso (meglio) convertire un'opzione restituita da una chiamata di metodo in una Prova (di preferenza, anche se un E o uno scalaz \/
o anche una Convalida potrebbe essere OK) includendo anche un valore di Errore se appropriato?Come posso (meglio) convertire un'opzione in una prova?
Per esempio, ho il seguente codice, che si sente kludgy, ma che almeno fa (la maggior parte) il lavoro:
import scala.util._
case class ARef(value: String)
case class BRef(value: String)
case class A(ref: ARef, bRef: BRef)
class MismatchException(msg: String) extends RuntimeException(msg)
trait MyTry {
// Given:
val validBRefs: List[BRef]
// Want to go from an Option[A] (obtained, eg., via a function call passing a provided ARef)
// to a Try[BRef], where the b-ref needs to be checked against the above list of BRefs or fail:
def getValidBRefForReferencedA(aRef: ARef): Try[BRef] = {
val abRef = for {
a <- get[A](aRef) // Some function that returns an Option[A]
abRef = a.bRef
_ <- validBRefs.find(_ == abRef)
} yield (abRef)
abRef match {
case Some(bRef) => Success(bRef)
case None => Failure(new MismatchException("No B found matching A's B-ref"))
}
}
}
Ci si sente come se ci dovrebbe essere un modo per la finale di essere trasformato in una mappa o in una mappa piatta o in un costrutto simile e incorporato nella precedente per la comprensione.
Inoltre, preferirei essere in grado di specificare un messaggio di errore diverso se la chiamata per restituire un'opzione [A] da ARef non è riuscita (restituito None) rispetto al controllo BRef non riuscito (mi interessa solo conoscere una ragione per il fallimento, quindi una convalida scalatica non si sente come l'ideale).
È questo un luogo adatto per utilizzare un trasformatore monad? Se è così, scalaz ne fornisce uno adatto o qualcuno può dare un esempio di come sarebbe?
Intendi qualcosa come 'Prova {abRef.getOrElse (lancia nuova MismatchException (" Nessun B trovato che corrisponde a A's B-ref "))}' o 'abRef.map {Success (_)} .getOrElse (Fallimento (nuova MismatchException ("Nessun B trovato corrispondente a A's B-ref"))) '? – senia
@senia più quest'ultimo: 'abRef.map {Success (_)} .getOrElse (Failure (new MismatchException (" Nessun B trovato che corrisponde a A's B-ref ")))', ma sembra che dovrebbe essere possibile - e più idiomatico - per costruire questo nella comprensione per qualche motivo. – Shadowlands
Come nota a margine, perché non usare 'filter' su' Option'-ie, sostituisci il tuo 'for'-comprehension con' get [A] (aRef) .map (_. BRef) .filter (validBRefs.contains) ' ? –