Transformer for Either
, allowing the effect of an arbitrary type constructor F
to be combined with the
fail-fast effect of Either
.
EitherT[F, A, B]
wraps a value of type F[Either[A, B]]
. An F[C]
can be lifted in to EitherT[F, A, C]
via EitherT.right
,
and lifted in to a EitherT[F, C, B]
via EitherT.left
.
- Companion:
- object
Value members
Concrete methods
Combine leftSemiflatMap
and semiflatMap
together.
Combine leftSemiflatMap
and semiflatMap
together.
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Left("abc"), Right(123)))
scala> eitherT.biSemiflatMap(string => List(string.length), int => List(int.toFloat))
res0: cats.data.EitherT[List,Int,Float] = EitherT(List(Left(3), Right(123.0)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] =
| EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.bimap(string => string.length, int => int % 100)
res0: EitherT[List, Int, Int] = EitherT(List(Right(23), Left(3)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] =
| EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.collectRight
res0: List[Int] = List(123)
Similar to Either#combine
but mapped over an F
context.
Similar to Either#combine
but mapped over an F
context.
Examples:
scala> import cats.data.EitherT
scala> import cats.implicits._
scala> val l1: EitherT[Option, String, Int] = EitherT.left(Some("error 1"))
scala> val l2: EitherT[Option, String, Int] = EitherT.left(Some("error 2"))
scala> val r3: EitherT[Option, String, Int] = EitherT.right(Some(3))
scala> val r4: EitherT[Option, String, Int] = EitherT.right(Some(4))
scala> val noneEitherT: EitherT[Option, String, Int] = EitherT.left(None)
scala> l1 combine l2
res0: EitherT[Option, String, Int] = EitherT(Some(Left(error 1)))
scala> l1 combine r3
res1: EitherT[Option, String, Int] = EitherT(Some(Left(error 1)))
scala> r3 combine l1
res2: EitherT[Option, String, Int] = EitherT(Some(Left(error 1)))
scala> r3 combine r4
res3: EitherT[Option, String, Int] = EitherT(Some(Right(7)))
scala> l1 combine noneEitherT
res4: EitherT[Option, String, Int] = EitherT(None)
scala> noneEitherT combine l1
res5: EitherT[Option, String, Int] = EitherT(None)
scala> r3 combine noneEitherT
res6: EitherT[Option, String, Int] = EitherT(None)
scala> noneEitherT combine r4
res7: EitherT[Option, String, Int] = EitherT(None)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val e1: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> e1.ensure("error")(_ > 150)
res0: EitherT[List, String, Int] = EitherT(List(Left(error), Left(abc)))
scala> val e2: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> e2.ensure("error")(_ > 100)
res1: EitherT[List, String, Int] = EitherT(List(Right(123), Left(abc)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val e1: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> e1.ensureOr(_ => "error")(_ > 100)
res0: EitherT[List, String, Int] = EitherT(List(Right(123), Left(abc)))
scala> val e2: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> e2.ensureOr(_ => "error")(_ > 150)
res1: EitherT[List, String, Int] = EitherT(List(Left(error), Left(abc)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.exists(_ > 100)
res0: List[Boolean] = List(true, false)
Transform this EitherT[F, A, B]
into a F[C]
.
Transform this EitherT[F, A, B]
into a F[C]
.
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Left("456"), Right(123)))
scala> eitherT.fold(string => string.toInt, int => int)
res0: List[Int] = List(456, 123)
Transform this EitherT[F, A, B]
into a F[C]
.
Transform this EitherT[F, A, B]
into a F[C]
.
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123),Left("abc")))
scala> eitherT.foldF(string => string.split("").toList, _ => List("123"))
res0: List[String] = List(123, a, b, c)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.forall(_ > 100)
res0: List[Boolean] = List(true, true)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> eitherT.getOrElse(456)
res0: List[Int] = List(123, 456)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> eitherT.getOrElseF(List(456))
res0: List[Int] = List(123, 456)
Like getOrElseF but accept an error E
and raise it when the inner Either
is Left
Like getOrElseF but accept an error E
and raise it when the inner Either
is Left
Equivalent to getOrElseF(F.raiseError(e)))
Example:
scala> import cats.data.EitherT
scala> import cats.implicits._
scala> import scala.util.{Success, Failure, Try}
scala> val eitherT: EitherT[Try,String,Int] = EitherT[Try,String,Int](Success(Left("abc")))
scala> eitherT.getOrRaise(new RuntimeException("ERROR!"))
res0: Try[Int] = Failure(java.lang.RuntimeException: ERROR!)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> eitherT.isLeft
res0: List[Boolean] = List(false, true)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> eitherT.isRight
res0: List[Boolean] = List(true, false)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val e1: EitherT[Option,String,Int] = EitherT[Option, String,Int](Some(Right(123)))
scala> e1.orElse(EitherT[Option,Boolean,Int](Some(Right(456))))
res0: EitherT[Option, Boolean, Int] = EitherT(Some(Right(123)))
scala> val e2: EitherT[Option,String,Int] = EitherT[Option, String,Int](Some(Left("abc")))
scala> e2.orElse(EitherT[Option,Boolean,Int](Some(Left(true))))
res1: EitherT[Option, Boolean, Int] = EitherT(Some(Left(true)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] =
| EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> val pf: PartialFunction[String, Int] = {case "abc" => 456}
scala> eitherT.recover(pf)
res0: EitherT[List, String, Int] = EitherT(List(Right(123), Right(456)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] =
| EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> val pf: PartialFunction[String, EitherT[List, String, Int]] =
| {case "abc" => EitherT[List, String, Int](List(Right(456)))}
scala> eitherT.recoverWith(pf)
res0: EitherT[List, String, Int] = EitherT(List(Right(123), Right(456)))
Inverse of MonadError#attemptT
Given MonadError[F, E :> A] transforms Either[F, A, B] to F[B]
If the value was B, F[B] is successful
If the value was A, F[B] is failed with E
Inverse of MonadError#attemptT
Given MonadError[F, E :> A] transforms Either[F, A, B] to F[B]
If the value was B, F[B] is successful
If the value was A, F[B] is failed with E
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val e1: EitherT[Option, Unit, Int] = EitherT[Option, Unit, Int](Some(Right(123)))
scala> e1.rethrowT
res0: Option[Int] = Some(123)
scala> val e2: EitherT[Option, Unit, Int] = EitherT[Option, Unit, Int](Some(Left(())))
scala> e2.rethrowT
res1: Option[Int] = None
scala> import scala.util.Try
scala> import java.lang.Exception
scala> val e3: EitherT[Try, Throwable, String] = EitherT[Try, Throwable, String](Try(Right("happy cats")))
scala> e3.rethrowT
res2: util.Try[String] = Success(happy cats)
scala> val e4: EitherT[Try, Throwable, String] = EitherT[Try, Throwable, String](Try(Left(new Exception("sad cats"))))
scala> e4.rethrowT
res3: util.Try[String] = Failure(java.lang.Exception: sad cats)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List,String,Int] = EitherT[List, String,Int](List(Right(123),Left("abc")))
scala> eitherT.swap
res0: EitherT[List,Int,String] = EitherT(List(Left(123), Right(abc)))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.to[Option]
res0: List[Option[Int]] = List(Some(123), None)
Convert this EitherT[F, A, B]
into an IorT[F, A, B]
.
Convert this EitherT[F, A, B]
into an IorT[F, A, B]
.
Transform this EitherT[F, A, B]
into a [[Nested]][F, Either[A, *], B]
.
Transform this EitherT[F, A, B]
into a [[Nested]][F, Either[A, *], B]
.
An example where toNested
can be used, is to get the Apply.ap
function with the
behavior from the composed Apply
instances from F
and Either[A, *]
, which is
inconsistent with the behavior of the ap
from Monad
of EitherT
.
scala> import cats.data.EitherT
scala> import cats.implicits._
scala> val ff: EitherT[List, String, Int => String] =
| EitherT(List(Either.right(_.toString), Either.left("error")))
scala> val fa: EitherT[List, String, Int] =
| EitherT(List(Either.right(1), Either.right(2)))
scala> ff.ap(fa)
res0: EitherT[List,String,String] = EitherT(List(Right(1), Right(2), Left(error)))
scala> EitherT((ff.toNested).ap(fa.toNested).value)
res1: EitherT[List,String,String] = EitherT(List(Right(1), Right(2), Left(error), Left(error)))
Transform this EitherT[F, A, B]
into a [[Nested]][F, Validated[A, *], B]
.
Transform this EitherT[F, A, B]
into a [[Nested]][F, Validated[A, *], B]
.
Example:
scala> import cats.data.{EitherT, Validated}
scala> import cats.implicits._
scala> val f: Int => String = i => (i*2).toString
scala> val r1: EitherT[Option, String, Int => String] = EitherT.right(Some(f))
r1: cats.data.EitherT[Option,String,Int => String] = EitherT(Some(Right(<function1>)))
scala> val r2: EitherT[Option, String, Int] = EitherT.right(Some(10))
r2: cats.data.EitherT[Option,String,Int] = EitherT(Some(Right(10)))
scala> type ErrorOr[A] = Validated[String, A]
scala> (r1.toNestedValidated).ap(r2.toNestedValidated)
res0: cats.data.Nested[Option,ErrorOr,String] = Nested(Some(Valid(20)))
Transform this EitherT[F, A, B]
into a [[Nested]][F, ValidatedNec[A, *], B]
.
Transform this EitherT[F, A, B]
into a [[Nested]][F, ValidatedNec[A, *], B]
.
Transform this EitherT[F, A, B]
into a [[Nested]][F, ValidatedNel[A, *], B]
.
Transform this EitherT[F, A, B]
into a [[Nested]][F, ValidatedNel[A, *], B]
.
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.toOption
res0: OptionT[List, Int] = OptionT(List(Some(123), None))
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.valueOr(_.length)
res0: List[Int] = List(123, 3)
Example:
Example:
scala> import cats.implicits._
scala> import cats.data.EitherT
scala> val eitherT: EitherT[List, String, Int] = EitherT[List, String, Int](List(Right(123), Left("abc")))
scala> eitherT.valueOrF(string => List(string.length))
res0: List[Int] = List(123, 3)
Run this value as a [[Validated]]
against the function and convert it back to an [[EitherT]]
.
Run this value as a [[Validated]]
against the function and convert it back to an [[EitherT]]
.
The Applicative instance for EitherT
"fails fast" - it is often useful to "momentarily" have
it accumulate errors instead, which is what the [[Validated]]
data type gives us.
Example:
scala> import cats.implicits._
scala> type Error = String
scala> val v1: Validated[NonEmptyList[Error], Int] = Validated.invalidNel("error 1")
scala> val v2: Validated[NonEmptyList[Error], Int] = Validated.invalidNel("error 2")
scala> val eithert: EitherT[Option, Error, Int] = EitherT.leftT[Option, Int]("error 3")
scala> eithert.withValidated { v3 => (v1, v2, v3.toValidatedNel).mapN { case (i, j, k) => i + j + k } }
res0: EitherT[Option, NonEmptyList[Error], Int] = EitherT(Some(Left(NonEmptyList(error 1, error 2, error 3))))