Questa operazione viene spesso chiamato sequenziamento, ed è disponibile nelle librerie standard di alcuni linguaggi funzionali (come Haskell). In Scala puoi implementare il tuo o usare una libreria esterna come Scalaz. Supponiamo di avere il seguente, ad esempio:
val xs: List[Either[String, Int]] = List(Right(1), Right(2))
val ys: List[Either[String, Int]] = List(Right(1), Left("1st!"), Left("2nd!"))
Ora possiamo scrivere (usando Scalaz 7):
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> xs.sequenceU
res0: Either[String,List[Int]] = Right(List(1, 2))
scala> ys.sequenceU
res1: Either[String,List[Int]] = Left(1st!)
come desiderato.
Come nota, questa operazione richiede solo che il contenitore esterno sia attraversabile e che il contenitore interno tramite un funtore applicativo. Scalaz fornisce anche una classe ValidationNEL
che è un po 'come Either
e anche adatta a questi requisiti, ma utilizzando sequence
su un elenco di ValidationNEL
s raccoglie più errori invece di fermarsi alla prima:
val zs: List[ValidationNEL[String, Int]] =
List(1.successNel, "1st".failNel, "2nd".failNel)
Ora otteniamo:
scala> print(zs.sequenceU)
Failure(NonEmptyList(1st, 2nd))
si potrebbe anche usare sequence
su un elenco di Option
s, Promise
s, ecc
fonte
2012-10-28 21:48:57
La trasformazione che si vuole raggiungere è un po 'ambigua. La tua lista di input contiene per esempio la metà di 'Right [String]' se metà di vari ed eterogenei 'Left [Exception]' s. Si vuole ridurlo a una sola eccezione o lista di stringhe. Quale eccezione dovrebbe essere presa se ci fossero, ad es. dieci diversi nell'input? –
Hai ragione. Voglio considerare solo la prima eccezione (o qualsiasi valore Left) che nasconderà altri, ma è accettabile per il mio caso d'uso. –
Questo è un duplicato di http://stackoverflow.com/questions/7230999/how-to-reduce-a-seqeithera-b-to-a-eitherseqa-seqb. – ziggystar