Search code examples
scalascala-catseitherscala-option

How to turn `Either[Error, Option[Either[Error, Account]]]` to `Either[Error, Option[Account]]` with typelevel cats?


I'm using cats, wonder how to turn a data with it.

From

val data = Either[Error, Option[Either[Error, Account]]]

to

val target: Either[Error, Option[Account]] = howToConvert(data)

If there is any Error happens, the result will be Left(error) with the first appeared error.

I can do it now with:

data match {
  case Left(e) => Left(e)
  case Right(Some(Right(y))) => Right(Some(y))
  case Right(Some(Left(e))) => Left(e)
  case Right(None) => Right(None)
}

But I'm looking for some easy way


Solution

  • The easiest way to do this is to sequence the inner Option, so that you get an Either[Error, Either[Error, Option[Account]]] and then flatten it. With cats syntax this is really easy:

    import cats.implicits._
    
    val target: Either[Error, Option[Account]] =
      data.flatMap(_.sequence)
    

    To clarify, sequence turns a type constructor "inside out", meaning the inner Option[Either[Error, Account]] is turned into an Either[Error, Option[Account]].