From b5a795f6919f0bea770dd39959a00ef0f2819e3b Mon Sep 17 00:00:00 2001 From: Hamed Nourhani Date: Wed, 11 Sep 2019 09:11:57 +0430 Subject: [PATCH] add more doctest to EitherT --- core/src/main/scala/cats/data/EitherT.scala | 257 +++++++++++++++++++- 1 file changed, 256 insertions(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index 18b4d3f57a..2b65c34595 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -1,7 +1,6 @@ package cats package data -import cats.Bifunctor import cats.instances.either._ import cats.syntax.either._ @@ -13,33 +12,155 @@ import cats.syntax.either._ * and lifted in to a `EitherT[F, C, B]` via `EitherT.left`. */ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) { + + /** 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) + * }}} + */ def fold[C](fa: A => C, fb: B => C)(implicit F: Functor[F]): F[C] = F.map(value)(_.fold(fa, fb)) + /** 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, int => List(s"$int")) + * res0: List[String] = List(123, a, b, c) + * }}} + */ def foldF[C](fa: A => F[C], fb: B => F[C])(implicit F: FlatMap[F]): F[C] = F.flatMap(value)(_.fold(fa, fb)) + /** + * 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) + * }}} + */ def isLeft(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.isLeft) + /** + * 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) + * }}} + */ def isRight(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.isRight) + /** + * 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))) + * }}} + */ def swap(implicit F: Functor[F]): EitherT[F, B, A] = EitherT(F.map(value)(_.swap)) + /** + * 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) + * }}} + */ def getOrElse[BB >: B](default: => BB)(implicit F: Functor[F]): F[BB] = F.map(value)(_.getOrElse(default)) + /** + * 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) + * }}} + */ def getOrElseF[BB >: B](default: => F[BB])(implicit F: Monad[F]): F[BB] = F.flatMap(value) { case Left(_) => default case Right(b) => F.pure(b) } + /** + * 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))) + * }}} + */ def orElse[C, BB >: B](default: => EitherT[F, C, BB])(implicit F: Monad[F]): EitherT[F, C, BB] = EitherT(F.flatMap(value) { case Left(_) => default.value case r @ Right(_) => F.pure(r.leftCast) }) + /** + * 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))) + * }}} + */ def recover(pf: PartialFunction[A, B])(implicit F: Functor[F]): EitherT[F, A, B] = EitherT(F.map(value)(_.recover(pf))) + /** + * 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))) + * }}} + */ def recoverWith(pf: PartialFunction[A, EitherT[F, A, B]])(implicit F: Monad[F]): EitherT[F, A, B] = EitherT(F.flatMap(value) { case Left(a) if pf.isDefinedAt(a) => pf(a).value @@ -48,36 +169,170 @@ final case class EitherT[F[_], A, B](value: F[Either[A, B]]) { /** * Inverse of `MonadError#attemptT` + * + * 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 + * }}} */ def rethrowT(implicit F: MonadError[F, _ >: A]): F[B] = F.rethrow(value) + /** + * 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) + * }}} + */ def valueOr[BB >: B](f: A => BB)(implicit F: Functor[F]): F[BB] = fold(f, identity) + /** + * 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) + * }}} + */ def valueOrF[BB >: B](f: A => F[BB])(implicit F: Monad[F]): F[BB] = F.flatMap(value) { case Left(a) => f(a) case Right(b) => F.pure(b) } + /** + * 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) + * }}} + */ def forall(f: B => Boolean)(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.forall(f)) + /** + * 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) + * }}} + */ def exists(f: B => Boolean)(implicit F: Functor[F]): F[Boolean] = F.map(value)(_.exists(f)) + /** + * 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))) + * }}} + */ def ensure[AA >: A](onFailure: => AA)(f: B => Boolean)(implicit F: Functor[F]): EitherT[F, AA, B] = EitherT(F.map(value)(_.ensure(onFailure)(f))) + /** + * 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(int => s"$int")(_ > 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(int => s"$int")(_ > 150) + * res1: EitherT[List, String, Int] = EitherT(List(Left(123), Left(abc))) + * }}} + */ def ensureOr[AA >: A](onFailure: B => AA)(f: B => Boolean)(implicit F: Functor[F]): EitherT[F, AA, B] = EitherT(F.map(value)(_.ensureOr(onFailure)(f))) + /** + * 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)) + * }}} + */ def toOption(implicit F: Functor[F]): OptionT[F, B] = OptionT(F.map(value)(_.toOption)) + /** + * 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) + * }}} + */ def to[G[_]](implicit F: Functor[F], G: Alternative[G]): F[G[B]] = F.map(value)(_.to[G]) + /** + * 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) + * }}} + */ def collectRight(implicit FA: Alternative[F], FM: Monad[F]): F[B] = FM.flatMap(value)(_.to[F]) + /** + * 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))) + * }}} + */ def bimap[C, D](fa: A => C, fb: B => D)(implicit F: Functor[F]): EitherT[F, C, D] = EitherT(F.map(value)(_.bimap(fa, fb)))