Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 590
Freewind Avatar asked Jan 15 '18 04:01

Freewind


2 Answers

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]].

like image 111
Luka Jacobowitz Avatar answered Oct 22 '22 23:10

Luka Jacobowitz


Here's an "easy" way that only assumes a right-biased Either (Scala 2.12), or cats' syntax

val target: Either[Error, Option[Account]] =
    data.flatMap(_.map(_.map(Some(_))).getOrElse(Right(None)))
like image 29
thesamet Avatar answered Oct 22 '22 21:10

thesamet