Ecco alcune cose utili:
def sysValue(prop: String) = Option(System.getProperty(prop)) //returns Option[String]
def trySysValue(prop: String) = //returns Either[String, String]
sysValue(prop) map Right getOrElse Left("Absent property: " + prop)
Poi si può usare composizione monadico Either
attraverso la sua destro proiezione
val batch = //batch is Either[String, (File, File)]
for {
x <- trySysValue("XDir")).right
xf <- dir(x).right
y <- trySysValue("YDir").right
yf <- dir(y).right
}
yield (xf, yf)
Dove:
def dir(s: String) = { //returns Either[String, File]
val f = new File(s)
if (!f.exists()) Left("Does not exist: " + f)
else if (!f.isDir()) Left("Is not a directory: " + f)
else Right(f)
}
Il lato sinistro di Either
sarà un messaggio di errore. Questa composizione monadica è fail fast. È possibile ottenere una composizione che accumuli tutti i guasti (ad esempio, se non esiste né XDir
né YDir
, si vedranno entrambi i messaggi) utilizzando scalazValidation
. In tal caso, il codice sarebbe simile a questa:
def trySysValue(prop: String) = //returns Validation[String, String]
sysValue(prop) map Success getOrElse ("Absent property: " + prop).fail
def dir(s: String) = {
val f = new File(s)
if (!f.exists())("Does not exist: " + f).fail
else if (!f.isDir()) ("Is not a directory: " + f).fail
else f.success
}
val batch = //batch is ValidationNEL[String, (File, File)]
(trySysValue("XDir")) flatMap dir).liftFailNel <|*|> (trySysValue("YDir")) flatMap dir).liftFailNel
fonte
2012-06-24 22:38:19
Posso codificare l'accumulo degli errori senza 'scalaz'? – Michael
Bene, potreste introdurre gli stessi concetti tramite la vostra libreria personale. Quello che stai cercando è una combinazione di ** funtori applicativi ** e ** monoidi **. Tuttavia, questi sono così utili e comuni, che si potrebbe anche solo usare lo scalaz. –
Ne parlo qui: http://skillsmatter.com/podcast/scala/practical-scalaz-2518 –