scalaz.LazyEitherT.scala Maven / Gradle / Ivy
The newest version!
package scalaz
final case class LazyEitherT[F[_], A, B](run: F[LazyEither[A, B]]) {
import LazyEither._
import LazyEitherT._
import OptionT._
import MaybeT._
import LazyOptionT._
def ?[X](left: => X, right: => X)(implicit F: Functor[F]): F[X] =
F.map(run)(_.fold(_ => left, _ => right))
def isLeft(implicit F: Functor[F]): F[Boolean] =
F.map(run)(_.isLeft)
def isRight(implicit F: Functor[F]): F[Boolean] =
F.map(run)(_.isRight)
def swap(implicit F: Functor[F]): F[LazyEither[B, A]] =
F.map(run)(_.swap)
def getOrElse(default: => B)(implicit F: Functor[F]): F[B] =
F.map(run)(_ getOrElse default)
/** Return the right value of this disjunction or the given default if left. Alias for `getOrElse` */
def |(default: => B)(implicit F: Functor[F]): F[B] =
getOrElse(default)
def exists(f: (=> B) => Boolean)(implicit F: Functor[F]): F[Boolean] =
F.map(run)(_ exists f)
def forall(f: (=> B) => Boolean)(implicit F: Functor[F]): F[Boolean] =
F.map(run)(_ forall f)
def orElse(x: => LazyEitherT[F, A, B])(implicit m: Bind[F]): LazyEitherT[F, A, B] = {
val g = run
LazyEitherT(m.bind(g)(_.fold(
_ => x.run
, _ => g
)))
}
/** Return this if it is a right, otherwise, return the given value. Alias for `orElse` */
def |||(x: => LazyEitherT[F, A, B])(implicit F: Bind[F]): LazyEitherT[F, A, B] =
orElse(x)
def toLazyOption(implicit F: Functor[F]): LazyOptionT[F, B] =
lazyOptionT(F.map(run)(_.toLazyOption))
def toOption(implicit F: Functor[F]): OptionT[F, B] =
optionT(F.map(run)(_.toOption))
def toMaybe(implicit F: Functor[F]): MaybeT[F, B] =
maybeT(F.map(run)(_.toMaybe))
def toList(implicit F: Functor[F]): F[List[B]] =
F.map(run)(_.toList)
def toIList(implicit F: Functor[F]): F[IList[B]] =
F.map(run)(_.toIList)
def toLazyList(implicit F: Functor[F]): F[LazyList[B]] =
F.map(run)(_.toLazyList)
def map[C](f: (=> B) => C)(implicit F: Functor[F]): LazyEitherT[F, A, C] =
lazyEitherT(F.map(run)(_ map f))
def flatMap[C](f: (=> B) => LazyEitherT[F, A, C])(implicit M: Monad[F]): LazyEitherT[F, A, C] =
lazyEitherT(M.bind(run)(_.fold(a => M.point(lazyLeft[C](a)), b => f(b).run)))
def bimap[C, D](f: (=> A) => C, g: (=> B) => D)(implicit F: Functor[F]): LazyEitherT[F, C, D] =
map(g).left.map(f)
/** Run the given function on the left value. */
def leftMap[C](f: (=> A) => C)(implicit F: Functor[F]): LazyEitherT[F, C, B] =
left.map(f)
def bitraverse[G[_], C, D](f: A => G[C], g: B => G[D])(implicit F: Traverse[F], G: Applicative[G]): G[LazyEitherT[F, C, D]] = {
Applicative[G].map(F.traverse(run)(Bitraverse[LazyEither].bitraverseF(f, g)))(LazyEitherT(_: F[LazyEither[C, D]]))
}
def traverse[G[_], C](f: B => G[C])(implicit F: Traverse[F], G: Applicative[G]): G[LazyEitherT[F, A, C]] = {
G.map(F.traverse(run)(o => LazyEither.lazyEitherInstance[A].traverse(o)(f)))(LazyEitherT(_))
}
def foldRight[Z](z: => Z)(f: (B, => Z) => Z)(implicit F: Foldable[F]): Z = {
F.foldr[LazyEither[A, B], Z](run, z)(a => b => LazyEither.lazyEitherInstance[A].foldRight[B, Z](a, b)(f))
}
/** Apply a function in the environment of the right of this
* disjunction. Because it runs my `F` even when `f`'s `\/` fails,
* it is not consistent with `ap`.
*/
def app[C](f: => LazyEitherT[F, A, B => C])(implicit F: Apply[F]): LazyEitherT[F, A, C] = {
// TODO check laziness
LazyEitherT[F, A, C](F.apply2(f.run, run)((ff: LazyEither[A, B => C], aa: LazyEither[A, B]) => LazyEither.lazyEitherInstance[A].ap(aa)(ff)))
}
def left: LeftProjectionT[F, A, B] = new LazyEitherT.LeftProjectionT[F, A, B](LazyEitherT.this)
}
object LazyEitherT extends LazyEitherTInstances {
def lazyEitherT[F[_], A, B](a: F[LazyEither[A, B]]): LazyEitherT[F, A, B] =
LazyEitherT(a)
def lazyEitherTU[FAB, AB, A0, B0](fab: FAB)(implicit
u1: Unapply[Functor, FAB]{type A = AB},
@deprecated("scala/bug#5075", "") u2: Unapply2[Bifunctor, AB]{type A = A0; type B = B0},
l: AB === LazyEither[A0, B0]
): LazyEitherT[u1.M, A0, B0] = LazyEitherT(l.subst[u1.M](u1(fab)))
import LazyEither._
def lazyLeftT[F[_], A, B](a: => A)(implicit p: Applicative[F]): LazyEitherT[F, A, B] =
lazyEitherT(p.point(lazyLeft(a)))
def lazyRightT[F[_], A, B](b: => B)(implicit p: Applicative[F]): LazyEitherT[F, A, B] =
lazyEitherT(p.point(lazyRight(b)))
import Isomorphism.{IsoFunctorTemplate, IsoBifunctorTemplate, <~>, <~~>}
def lazyEitherTLeftProjectionEIso2[F[_], E]: LazyEitherT.LeftProjectionT[F, E, *] <~> LazyEitherT[F, E, *] =
new IsoFunctorTemplate[LazyEitherT.LeftProjectionT[F, E, *], LazyEitherT[F, E, *]] {
def to_[A](fa: LazyEitherT.LeftProjectionT[F, E, A]): LazyEitherT[F, E, A] = fa.lazyEitherT
def from_[A](ga: LazyEitherT[F, E, A]): LazyEitherT.LeftProjectionT[F, E, A] = ga.left
}
def lazyEitherTLeftProjectionIso2[F[_]]: LazyEitherT.LeftProjectionT[F, *, *] <~~> LazyEitherT[F, *, *] =
new IsoBifunctorTemplate[LazyEitherT.LeftProjectionT[F, *, *], LazyEitherT[F, *, *]] {
def to_[A, B](fa: LazyEitherT.LeftProjectionT[F, A, B]): LazyEitherT[F, A, B] = fa.lazyEitherT
def from_[A, B](ga: LazyEitherT[F, A, B]): LazyEitherT.LeftProjectionT[F, A, B] = ga.left
}
final class LeftProjectionT[F[_], A, B](val lazyEitherT: LazyEitherT[F, A, B]) {
import OptionT._
import LazyOptionT._
def getOrElse(default: => A)(implicit F: Functor[F]): F[A] =
F.map(lazyEitherT.run)(_.left getOrElse default)
def exists(f: (=> A) => Boolean)(implicit F: Functor[F]): F[Boolean] =
F.map(lazyEitherT.run)(_.left exists f)
def forall(f: (=> A) => Boolean)(implicit F: Functor[F]): F[Boolean] =
F.map(lazyEitherT.run)(_.left forall f)
def orElse(x: => LazyEitherT[F, A, B])(implicit m: Bind[F]): LazyEitherT[F, A, B] = {
val g = lazyEitherT.run
LazyEitherT(m.bind(g)((z: LazyEither[A, B]) => z.fold(
_ => g
, _ => x.run
)))
}
def toLazyOption(implicit F: Functor[F]): LazyOptionT[F, A] =
lazyOptionT(F.map(lazyEitherT.run)(_.left.toLazyOption))
def toOption(implicit F: Functor[F]): OptionT[F, A] =
optionT(F.map(lazyEitherT.run)(_.left.toOption))
def toList(implicit F: Functor[F]): F[List[A]] =
F.map(lazyEitherT.run)(_.left.toList)
def toLazyList(implicit F: Functor[F]): F[LazyList[A]] =
F.map(lazyEitherT.run)(_.left.toLazyList)
def map[C](f: (=> A) => C)(implicit F: Functor[F]): LazyEitherT[F, C, B] =
LazyEitherT(F.map(lazyEitherT.run)(_.left map f))
def flatMap[C](f: (=> A) => LazyEitherT[F, C, B])(implicit M: Monad[F]): LazyEitherT[F, C, B] =
LazyEitherT(M.bind(lazyEitherT.run)(_.fold(a => f(a).run, b => M.point(LazyEither.lazyRight[C](b)))))
}
implicit def lazyEitherTMonadPlus[F[_], L](implicit F0: Monad[F], L: Monoid[L]): MonadPlus[LazyEitherT[F, L, *]] =
new LazyEitherTMonadPlus[F, L] {
override def E = L
override def F = F0
}
}
sealed abstract class LazyEitherTInstances1 {
implicit def lazyEitherTFunctor[F[_], L](implicit F0: Functor[F]): Functor[LazyEitherT[F, L, *]] =
new LazyEitherTFunctor[F, L] {
override def F = F0
}
implicit def lazyEitherTLeftProjectionFunctor[F[_], L](implicit F0: Functor[F]): Functor[LazyEitherT.LeftProjectionT[F, L, *]] =
new IsomorphismFunctor[LazyEitherT.LeftProjectionT[F, L, *], LazyEitherT[F, L, *]] {
override def G = lazyEitherTFunctor[F, L]
def iso = LazyEitherT.lazyEitherTLeftProjectionEIso2[F, L]
}
implicit def lazyEitherTMonadError[F[_], L](implicit F0: Monad[F]): MonadError[LazyEitherT[F, L, *], L] =
new LazyEitherTMonadError[F, L] {
override def F = F0
}
implicit def lazyEitherTPlus[F[_], L](implicit F0: Monad[F], L: Semigroup[L]): Plus[LazyEitherT[F, L, *]] =
new LazyEitherTPlus[F, L] {
override def F = F0
override def E = L
}
implicit def lazyEitherTAlt[F[_], L](implicit F0: Monad[F]): Alt[LazyEitherT[F, L, *]] =
new Alt[LazyEitherT[F, L, *]] with LazyEitherTMonad[F, L] {
override def F = F0
def alt[A](a: => LazyEitherT[F, L, A], b: => LazyEitherT[F, L, A]): LazyEitherT[F, L, A] =
LazyEitherT(
F.bind(a.run) { leA =>
F.map(b.run) {
Alt[LazyEither[L, *]].alt(leA, _)
}
}
)
}
}
sealed abstract class LazyEitherTInstances0 extends LazyEitherTInstances1 {
implicit def lazyEitherTBifunctor[F[_]](implicit F0: Functor[F]): Bifunctor[LazyEitherT[F, *, *]] =
new LazyEitherTBifunctor[F] {
override def F = F0
}
implicit def lazyEitherTBifoldable[F[_]](implicit F0: Foldable[F]): Bifoldable[LazyEitherT[F, *, *]] =
new LazyEitherTBifoldable[F] {
override def F = F0
}
implicit def lazyEitherTLeftProjectionBifunctor[F[_]](implicit F0: Functor[F]): Bifunctor[LazyEitherT.LeftProjectionT[F, *, *]] =
new IsomorphismBifunctor[LazyEitherT.LeftProjectionT[F, *, *], LazyEitherT[F, *, *]] {
override def G = lazyEitherTBifunctor[F]
def iso = LazyEitherT.lazyEitherTLeftProjectionIso2[F]
}
def lazyEitherTMonad[F[_], L](implicit F0: Monad[F]): Monad[LazyEitherT[F, L, *]] =
new LazyEitherTMonad[F, L] {
override def F = F0
}
implicit def lazyEitherTLeftProjectionMonad[F[_], L](implicit F0: Monad[F]): Monad[LazyEitherT.LeftProjectionT[F, L, *]] =
new IsomorphismMonad[LazyEitherT.LeftProjectionT[F, L, *], LazyEitherT[F, L, *]] {
override def G = lazyEitherTMonad[F, L]
def iso = LazyEitherT.lazyEitherTLeftProjectionEIso2[F, L]
}
implicit def lazyEitherTFoldable[F[_], L](implicit F0: Foldable[F]): Foldable[LazyEitherT[F, L, *]] =
new LazyEitherTFoldable[F, L] {
override def F = F0
}
implicit def lazyEitherTLeftProjectionFoldable[F[_], L](implicit F0: Foldable[F]): Foldable[LazyEitherT.LeftProjectionT[F, L, *]] =
new IsomorphismFoldable[LazyEitherT.LeftProjectionT[F, L, *], LazyEitherT[F, L, *]] {
override def G = lazyEitherTFoldable[F, L]
def naturalTrans = LazyEitherT.lazyEitherTLeftProjectionEIso2[F, L].to
}
implicit def lazyEitherTBindRec[F[_], L](implicit F0: Monad[F], B0: BindRec[F]): BindRec[LazyEitherT[F, L, *]] =
new LazyEitherTBindRec[F, L] {
override def F = F0
override def B = B0
}
}
// TODO more instances
sealed abstract class LazyEitherTInstances extends LazyEitherTInstances0 {
implicit def lazyEitherTBitraverse[F[_]](implicit F0: Traverse[F]): Bitraverse[LazyEitherT[F, *, *]] =
new LazyEitherTBitraverse[F] {
override def F = F0
}
implicit def lazyEitherTLeftProjectionBitraverse[F[_]](implicit F0: Traverse[F]): Bitraverse[LazyEitherT.LeftProjectionT[F, *, *]] =
new IsomorphismBitraverse[LazyEitherT.LeftProjectionT[F, *, *], LazyEitherT[F, *, *]] {
override def G = lazyEitherTBitraverse[F]
def iso = LazyEitherT.lazyEitherTLeftProjectionIso2[F]
}
implicit def lazyEitherTTraverse[F[_], L](implicit F0: Traverse[F]): Traverse[LazyEitherT[F, L, *]] =
new LazyEitherTTraverse[F, L] {
override def F = F0
}
implicit def lazyEitherTLeftProjectionTraverse[F[_], L](implicit F0: Traverse[F]): Traverse[LazyEitherT.LeftProjectionT[F, L, *]] =
new IsomorphismTraverse[LazyEitherT.LeftProjectionT[F, L, *], LazyEitherT[F, L, *]] {
override def G = lazyEitherTTraverse[F, L]
def iso = LazyEitherT.lazyEitherTLeftProjectionEIso2[F, L]
}
implicit def lazyEitherTHoist[A]: Hoist[({type l[a[_], b] = LazyEitherT[a, A, b]})#l] =
new Hoist[({type l[a[_], b] = LazyEitherT[a, A, b]})#l] {
override def hoist[M[_]: Monad, N[_]](f: M ~> N): LazyEitherT[M, A, *] ~> LazyEitherT[N, A, *] =
new (LazyEitherT[M, A, *] ~> LazyEitherT[N, A, *]) {
def apply[B](mb: LazyEitherT[M, A, B]) = LazyEitherT(f(mb.run))
}
override def liftM[M[_], B](mb: M[B])(implicit M: Monad[M]) =
LazyEitherT(M.map(mb)(LazyEither.lazyRight[A].apply(_)))
override def apply[M[_]: Monad] =
LazyEitherT.lazyEitherTMonad[M, A]
}
}
//
// Type class implementation traits
//
private trait LazyEitherTFunctor[F[_], E] extends Functor[LazyEitherT[F, E, *]] {
implicit def F: Functor[F]
override final def map[A, B](fa: LazyEitherT[F, E, A])(f: A => B): LazyEitherT[F, E, B] = fa map (a => f(a))
}
private trait LazyEitherTMonad[F[_], E] extends Monad[LazyEitherT[F, E, *]] with LazyEitherTFunctor[F, E] {
implicit def F: Monad[F]
def point[A](a: => A): LazyEitherT[F, E, A] = LazyEitherT.lazyRightT(a)
def bind[A, B](fa: LazyEitherT[F, E, A])(f: A => LazyEitherT[F, E, B]): LazyEitherT[F, E, B] = fa flatMap (a => f(a))
}
private trait LazyEitherTPlus[F[_], E] extends Plus[LazyEitherT[F, E, *]] {
implicit def F: Monad[F]
def E: Semigroup[E]
override def plus[A](a: LazyEitherT[F, E, A], b: => LazyEitherT[F, E, A]) =
LazyEitherT(F.bind(a.run){ r =>
r.fold(
l => F.map(b.run){ rr =>
rr.fold(
ll => LazyEither.lazyLeft(E.append(l, ll)),
_ => rr
)
},
_ => F.point(r)
)
})
}
private trait LazyEitherTMonadPlus[F[_], E] extends MonadPlus[LazyEitherT[F, E, *]] with LazyEitherTMonad[F, E] with LazyEitherTPlus[F, E] {
override def E: Monoid[E]
override def empty[A] = LazyEitherT.lazyLeftT(E.zero)
}
private trait LazyEitherTFoldable[F[_], E] extends Foldable.FromFoldr[LazyEitherT[F, E, *]] {
implicit def F: Foldable[F]
override final def foldRight[A, B](fa: LazyEitherT[F, E, A], z: => B)(f: (A, => B) => B): B = fa.foldRight(z)(f)
}
private trait LazyEitherTTraverse[F[_], E] extends Traverse[LazyEitherT[F, E, *]] with LazyEitherTFoldable[F, E] with LazyEitherTFunctor[F, E] {
implicit def F: Traverse[F]
def traverseImpl[G[_]: Applicative, A, B](fa: LazyEitherT[F, E, A])(f: A => G[B]): G[LazyEitherT[F, E, B]] = fa traverse f
}
private trait LazyEitherTBifunctor[F[_]] extends Bifunctor[LazyEitherT[F, *, *]] {
implicit def F: Functor[F]
override final def bimap[A, B, C, D](fab: LazyEitherT[F, A, B])(f: A => C, g: B => D) =
fab.map(x => g(x)).left.map(x => f(x))
}
private trait LazyEitherTBifoldable[F[_]] extends Bifoldable.FromBifoldMap[LazyEitherT[F, *, *]] {
implicit def F: Foldable[F]
override final def bifoldMap[A, B, M: Monoid](fab: LazyEitherT[F, A, B])(f: A => M)(g: B => M) =
F.foldMap(fab.run)(Bifoldable[LazyEither].bifoldMap(_)(f)(g))
}
private trait LazyEitherTBitraverse[F[_]] extends Bitraverse[LazyEitherT[F, *, *]] with LazyEitherTBifunctor[F] with LazyEitherTBifoldable[F] {
implicit def F: Traverse[F]
def bitraverseImpl[G[_]: Applicative, A, B, C, D](fab: LazyEitherT[F, A, B])(f: A => G[C], g: B => G[D]): G[LazyEitherT[F, C, D]] =
Applicative[G].map(F.traverse(fab.run)(Bitraverse[LazyEither].bitraverseF(f, g)))(LazyEitherT.lazyEitherT(_))
}
private trait LazyEitherTBindRec[F[_], E] extends BindRec[LazyEitherT[F, E, *]] with LazyEitherTMonad[F, E] {
implicit def B: BindRec[F]
final def tailrecM[A, B](a: A)(f: A => LazyEitherT[F, E, A \/ B]): LazyEitherT[F, E, B] =
LazyEitherT(
B.tailrecM[A, LazyEither[E, B]](a)(a => F.map(f(a).run) {
_.fold(e => \/-(LazyEither.lazyLeft(e)), _.map(b => LazyEither.lazyRight(b)))
})
)
}
private trait LazyEitherTMonadError[F[_], E] extends MonadError[LazyEitherT[F, E, *], E] with LazyEitherTMonad[F, E] {
def raiseError[A](e: E): LazyEitherT[F, E, A] = LazyEitherT.lazyLeftT(e)
def handleError[A](fa: LazyEitherT[F, E, A])(f: E => LazyEitherT[F, E, A]): LazyEitherT[F, E, A] = fa.left.flatMap(e => f(e))
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy