[SOLVED] Turning List[Either[A, B]] into Either[A, List[B]]

I am looking for the best way to turn a List[Either[A, B]] into an Either[A, List[B]] where Left of the result should contain the first Left from the input.

Example:

Given the input is a list containing (Right(1), Right(2), Left("Error"), Right(3)) the result should be Left("Error").

Given the input is a list containing (Right(1), Right(2), Right(3)) the result should be Right(List(1, 2, 3)).

Any ideas? I am winding up my head but cannot get around the solution.

This is available generically in Cats as traverse. If you do not want to add a dependency I would start with a simple imperative solution and then abstract it from there as you need it, e.g.

def traverse[A, B](eithers: List[Either[A, B]]): Either[A, List[B]] = {
  val builder = List.newBuilder[B]
  val it = eithers.iterator

  while (it.hasNext) it.next() match {
    case Left(a) => return Left(a)
    case Right(b) => builder += b
  }

  Right(builder.result())
}
1 Like

In Scala 2.13 the solution is simple:

  val (lefts, rights) = eithers.partitionMap(identity)
  val result = lefts.headOption.toLeft(rights)

Example: https://scastie.scala-lang.org/8MuTTHf2TxW288EJk0JPtg

2 Likes

To be completely correct, I think this function is called sequence. traverse is generalization of that.

Thank you, did not thing it could be so simple :slight_smile: