operacja ta jest często nazywana sekwencjonowanie i jest dostępny w standardowych bibliotekach niektórych języków funkcyjnych (takich jak Haskell). W Scali możesz wdrożyć własne lub użyć zewnętrznej biblioteki, takiej jak Scalaz. Załóżmy, że mamy następujące, na przykład:
val xs: List[Either[String, Int]] = List(Right(1), Right(2))
val ys: List[Either[String, Int]] = List(Right(1), Left("1st!"), Left("2nd!"))
Teraz możemy napisać (przy użyciu 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!)
zgodnie z zapotrzebowaniem.
Na marginesie ta operacja wymaga jedynie, aby pojemnik zewnętrzny był przesuwny, a pojemnik wewnętrzny był aplikatorem. Scalaz zapewnia również ValidationNEL
klasy, który jest bardzo podobny Either
a także spełnia te wymagania, ale stosując sequence
na liście ValidationNEL
s zbiera wiele błędów, zamiast zatrzymać się na pierwszym:
val zs: List[ValidationNEL[String, Int]] =
List(1.successNel, "1st".failNel, "2nd".failNel)
Teraz otrzymujemy:
scala> print(zs.sequenceU)
Failure(NonEmptyList(1st, 2nd))
można również użyć sequence
na liście Option
s, Promise
s itd
transformacji chcesz osiągnąć jest nieco dwuznaczne. Twoja lista wejściowa zawiera na przykład połowę 'Right [String]' s oraz połowę różnych i heterogenicznych 'Left [Exception]' s. Chcesz zmniejszyć do jednego wyjątku lub listy ciągów. Który wyjątek należy zastosować, jeśli np. dziesięć różnych w danych wejściowych? –
Masz rację. Chcę wziąć pod uwagę tylko pierwszy wyjątek (lub dowolną wartość lewą), który ukryje inne, ale jest to dopuszczalne w moim przypadku użycia. –
To jest duplikat http://stackoverflow.com/questions/7230999/how-to-reduce-a-seqeithera-b-to-a-eitherseqa-seqb. – ziggystar