I have some code like the below, where I have a list of Eithers, and I want to turn it into an Either of Lists ... in particular (in this case), if there are any Lefts in th
Starting in Scala 2.13
, most collections are now provided with a partitionMap method which partitions elements based on a function returning either Right
or Left
.
In our case, we don't even need a function that transforms our input into Right
or Left
to define the partitioning since we already have Right
s and Left
s. Thus a simple use of identity
!
Then it's just a matter of matching the resulting partitioned tuple of lefts and rights based on whether or not there are any lefts:
eithers.partitionMap(identity) match {
case (Nil, rights) => Right(rights)
case (lefts, _) => Left(lefts)
}
// * List[Either[String, Int]] = List(Right(3), Left("error x"), Right(7))
// => Either[List[String],List[Int]] = Left(List(error x))
// * List[Either[String, Int]] = List(Right(3), Right(7))
// => Either[List[String],List[Int]] = Right(List(3, 7))
For the understanding of partitionMap
here is the result of the intermediate step:
List(Right(3), Left("error x"), Right(7)).partitionMap(identity)
// (List[String], List[Int]) = (List(error x), List(3, 7))
data.partition(_.isLeft) match {
case (Nil, ints) => Right(for(Right(i) <- ints) yield i)
case (strings, _) => Left(for(Left(s) <- strings) yield s)
}
For one pass:
data.partition(_.isLeft) match {
case (Nil, ints) => Right(for(Right(i) <- ints.view) yield i)
case (strings, _) => Left(for(Left(s) <- strings.view) yield s)
}
If you want to have something more general and also functional then Validated
from cats library is the type you might want. It is something like Either
that can aggregate Errors. And in combination with NonEmptyList
it can be really powerful.
http://typelevel.org/cats/datatypes/validated.html