
scalaz.Kleisli.scala Maven / Gradle / Ivy
The newest version!
package scalaz
import Id._
/**
* Represents a function `A => M[B]`.
*/
final case class Kleisli[M[_], A, B](run: A => M[B]) { self =>
import Kleisli._
/** alias for `andThen` */
def >=>[C](k: Kleisli[M, B, C])(implicit b: Bind[M]): Kleisli[M, A, C] = kleisli((a: A) => b.bind(this(a))(k(_)))
def andThen[C](k: Kleisli[M, B, C])(implicit b: Bind[M]): Kleisli[M, A, C] = this >=> k
def >==>[C](k: B => M[C])(implicit b: Bind[M]): Kleisli[M, A, C] = this >=> kleisli(k)
def andThenK[C](k: B => M[C])(implicit b: Bind[M]): Kleisli[M, A, C] = this >==> k
/** alias for `compose` */
def <=<[C](k: Kleisli[M, C, A])(implicit b: Bind[M]): Kleisli[M, C, B] = k >=> this
def compose[C](k: Kleisli[M, C, A])(implicit b: Bind[M]): Kleisli[M, C, B] = k >=> this
def <==<[C](k: C => M[A])(implicit b: Bind[M]): Kleisli[M, C, B] = kleisli(k) >=> this
def composeK[C](k: C => M[A])(implicit b: Bind[M]): Kleisli[M, C, B] = this <==< k
def traverse[F[_]](f: F[A])(implicit M: Applicative[M], F: Traverse[F]): M[F[B]] =
F.traverse(f)(Kleisli.this(_))
def =<<(a: M[A])(implicit m: Bind[M]): M[B] = m.bind(a)(run)
def map[C](f: B => C)(implicit M: Functor[M]): Kleisli[M, A, C] =
kleisli(a => M.map(run(a))(f))
def mapK[N[_], C](f: M[B] => N[C]): Kleisli[N, A, C] =
kleisli(a => f(run(a)))
def flatMapK[C](f: B => M[C])(implicit M: Bind[M]): Kleisli[M, A, C] =
kleisli(a => M.bind(run(a))(f))
def flatMap[C](f: B => Kleisli[M, A, C])(implicit M: Bind[M]): Kleisli[M, A, C] =
kleisli((r: A) => M.bind[B, C](run(r))(((b: B) => f(b).run(r))))
def lift[L[_]: Applicative]: Kleisli[({type λ[α]=L[M[α]]})#λ, A, B] =
kleisli[({type λ[α]=L[M[α]]})#λ, A, B](a => Applicative[L].point(self(a)))
import Liskov._
def unlift[N[_], FF[_]](implicit M: Comonad[N], ev: this.type <~< Kleisli[({type λ[α] = N[FF[α]]})#λ, A, B]): Kleisli[FF, A, B] =
kleisli[FF, A, B]{a => Comonad[N].copoint(ev(self) run a)}
def unliftId[N[_]](implicit M: Comonad[N], ev: this.type <~< Kleisli[({type λ[α] = N[α]})#λ, A, B]): Reader[A, B] =
unlift[N, Id]
def rwst[W, S](implicit M: Functor[M], W: Monoid[W]): ReaderWriterStateT[M, A, W, S, B] = ReaderWriterStateT(
(r, s) => M.map(self(r)) {
b => (W.zero, b, s)
}
)
def state(implicit M: Functor[M]): StateT[M, A, B] =
StateT(a => M.map(run(a))((a, _)))
def liftMK[T[_[_], _]](implicit T: MonadTrans[T], M: Monad[M]): Kleisli[({type l[a] = T[M, a]})#l, A, B] =
mapK[({type l[a] = T[M, a]})#l, B](ma => T.liftM(ma))
def local[AA](f: AA => A): Kleisli[M, AA, B] = kleisli(f andThen run)
def endo(implicit M: Functor[M], ev: A >~> B): Endomorphic[({type λ[α, β] = Kleisli[M, α, β]})#λ, A] =
Endomorphic[({type λ[α, β] = Kleisli[M, α, β]})#λ, A](map(ev.apply))
}
//
// Prioritized Implicits for type class instances
//
sealed abstract class KleisliInstances8 {
implicit def kleisliFunctor[F[_], R](implicit F0: Functor[F]): Functor[({type λ[α] = Kleisli[F, R, α]})#λ] = new KleisliFunctor[F, R] {
implicit def F: Functor[F] = F0
}
}
sealed abstract class KleisliInstances7 extends KleisliInstances8 {
implicit def kleisliApply[F[_], R](implicit F0: Apply[F]): Apply[({type λ[α] = Kleisli[F, R, α]})#λ] = new KleisliApply[F, R] {
implicit def F: Apply[F] = F0
}
implicit def kleisliDistributive[F[_], R](implicit F0: Distributive[F]): Distributive[({type λ[α] = Kleisli[F, R, α]})#λ] = new KleisliDistributive[F, R] {
implicit def F: Distributive[F] = F0
}
}
sealed abstract class KleisliInstances6 extends KleisliInstances7 {
implicit def kleisliApplicative[F[_], R](implicit F0: Applicative[F]): Applicative[({type λ[α] = Kleisli[F, R, α]})#λ] = new KleisliApplicative[F, R] {
implicit def F: Applicative[F] = F0
}
implicit def kleisliPlus[F[_], A](implicit F0: Plus[F]): Plus[({type λ[α] = Kleisli[F, A, α]})#λ] = new KleisliPlus[F, A] {
implicit def F = F0
}
}
sealed abstract class KleisliInstances5 extends KleisliInstances6 {
implicit def kleisliApplicativePlus[F[_], R](implicit F0: ApplicativePlus[F]): ApplicativePlus[({type λ[α] = Kleisli[F, R, α]})#λ] = new ApplicativePlus[({type λ[α] = Kleisli[F, R, α]})#λ] with KleisliApplicative[F, R] with KleisliPlusEmpty[F, R] {
implicit def F: ApplicativePlus[F] = F0
}
implicit def kleisliSemigroup[F[_], A, B](implicit FB0: Semigroup[F[B]]): Semigroup[Kleisli[F, A, B]] = new KleisliSemigroup[F, A, B] {
implicit def FB = FB0
}
}
sealed abstract class KleisliInstances4 extends KleisliInstances5 {
implicit def kleisliMonadPlus[F[_], A](implicit F0: MonadPlus[F]): MonadPlus[({type λ[α] = Kleisli[F, A, α]})#λ] = new KleisliMonadPlus[F, A] {
implicit def F = F0
}
}
sealed abstract class KleisliInstances3 extends KleisliInstances4 {
implicit def kleisliMonadReader[F[_], R](implicit F0: Monad[F]): MonadReader[({type λ[α, β] = Kleisli[F, α, β]})#λ, R] = new KleisliMonadReader[F, R] {
implicit def F: Monad[F] = F0
}
}
sealed abstract class KleisliInstances2 extends KleisliInstances3 {
implicit def kleisliIdFunctor[R]: Functor[({type λ[α] = Kleisli[Id, R, α]})#λ] = kleisliFunctor[Id, R]
}
sealed abstract class KleisliInstances1 extends KleisliInstances2 {
implicit def kleisliIdApplicative[R]: Applicative[({type λ[α] = Kleisli[Id, R, α]})#λ] = kleisliApplicative[Id, R]
}
sealed abstract class KleisliInstances0 extends KleisliInstances1 {
implicit def kleisliIdApply[R]: Apply[({type λ[α] = Kleisli[Id, R, α]})#λ] = kleisliApply[Id, R]
implicit def kleisliProfunctor[F[_]](implicit F0: Functor[F]): Profunctor[({type λ[α, β]=Kleisli[F, α, β]})#λ] = new KleisliProfunctor[F] {
implicit def F = F0
}
implicit def kleisliCompose[F[_]](implicit F0: Bind[F]): Compose[({type λ[α, β]=Kleisli[F, α, β]})#λ] = new KleisliCompose[F] {
implicit def F = F0
}
}
abstract class KleisliInstances extends KleisliInstances0 {
implicit def kleisliArrow[F[_]](implicit F0: Monad[F]): Arrow[({type λ[α, β]=Kleisli[F, α, β]})#λ] with Choice[({type λ[α, β]=Kleisli[F, α, β]})#λ] = new KleisliArrow[F] {
implicit def F: Monad[F] = F0
}
implicit def kleisliContravariant[F[_], A]: Contravariant[({type λ[α] = Kleisli[F, α, A]})#λ] = new KleisliContravariant[F, A] {}
implicit def kleisliIdMonadReader[R]: MonadReader[({type λ[α, β] = Kleisli[Id, α, β]})#λ, R] = kleisliMonadReader[Id, R]
implicit def kleisliMonoid[F[_], A, B](implicit FB0: Monoid[F[B]]): Monoid[Kleisli[F, A, B]] = new KleisliMonoid[F, A, B] {
implicit def FB = FB0
}
implicit def kleisliPlusEmpty[F[_], A](implicit F0: PlusEmpty[F]): PlusEmpty[({type λ[α] = Kleisli[F, A, α]})#λ] = new KleisliPlusEmpty[F, A] {
implicit def F = F0
}
implicit def kleisliMonadTrans[R]: Hoist[({type λ[α[_], β] = Kleisli[α, R, β]})#λ] = new KleisliHoist[R] {}
implicit def kleisliCatchable[F[_], A](implicit F0: Catchable[F]): Catchable[({type λ[α] = Kleisli[F, A, α]})#λ] = new KleisliCatchable[F, A] {
implicit def F = F0
}
}
trait KleisliFunctions {
/**Construct a Kleisli from a Function1 */
def kleisli[M[_], A, B](f: A => M[B]): Kleisli[M, A, B] = Kleisli(f)
/** A version of `kleisli` that infers the type constructor `M`, when `M` is `Bind`
* @example
* {{{
* Kleisli.kleisliU{s: String => try \/-(s.toInt) catch{ case e: NumberFormatException => -\/(e) }}
* }}}
*/
def kleisliU[A, MB](f: A => MB)(implicit MB: Unapply[Bind, MB]): Kleisli[MB.M, A, MB.A] =
Kleisli(MB.leibniz.subst[({type λ[α] = A => α})#λ](f))
/**Implicitly unwrap the Function1 represented by the Kleisli */
implicit def kleisliFn[M[_], A, B](k: Kleisli[M, A, B]): A => M[B] = k.run
/**Pure Kleisli arrow */
def ask[M[_] : Monad, A]: Kleisli[M, A, A] = kleisli(a => Monad[M].point(a))
def local[M[_] : Monad, A, R](f: R => R)(fa: Kleisli[M, R, A]): Kleisli[M, R, A] = fa local f
}
object Kleisli extends KleisliInstances with KleisliFunctions
//
// Implementation traits for type class instances
//
import Kleisli.kleisli
//
// * -> *
//
private trait KleisliFunctor[F[_], R] extends Functor[({type λ[α] = Kleisli[F, R, α]})#λ] {
implicit def F: Functor[F]
override def map[A, B](fa: Kleisli[F, R, A])(f: A => B): Kleisli[F, R, B] = fa map f
}
private trait KleisliApply[F[_], R] extends Apply[({type λ[α] = Kleisli[F, R, α]})#λ] with KleisliFunctor[F, R] {
implicit def F: Apply[F]
override def ap[A, B](fa: => Kleisli[F, R, A])(f: => Kleisli[F, R, A => B]): Kleisli[F, R, B] = Kleisli[F, R, B](r => F.ap(fa(r))(f(r)))
}
private trait KleisliDistributive[F[_], R] extends Distributive[({type λ[α] = Kleisli[F, R, α]})#λ] with KleisliFunctor[F, R] {
implicit def F: Distributive[F]
override def distributeImpl[G[_]: Functor, A, B](a: G[A])(f: A => Kleisli[F, R, B]): Kleisli[F, R, G[B]] =
Kleisli(r => F.distribute(a)(f(_) run r))
}
private trait KleisliApplicative[F[_], R] extends Applicative[({type λ[α] = Kleisli[F, R, α]})#λ] with KleisliApply[F, R] {
implicit def F: Applicative[F]
def point[A](a: => A): Kleisli[F, R, A] = kleisli((r: R) => F.point(a))
}
private trait KleisliMonad[F[_], R] extends Monad[({type λ[α] = Kleisli[F, R, α]})#λ] with KleisliApplicative[F, R] {
implicit def F: Monad[F]
def bind[A, B](fa: Kleisli[F, R, A])(f: A => Kleisli[F, R, B]): Kleisli[F, R, B] = fa flatMap f
}
private trait KleisliMonadReader[F[_], R] extends MonadReader[({type f[s, a] = Kleisli[F, s, a]})#f, R] with KleisliApplicative[F, R] with KleisliMonad[F, R] {
implicit def F: Monad[F]
def ask: Kleisli[F, R, R] = Kleisli[F, R, R](r => F.point(r))
def local[A](f: R => R)(fa: Kleisli[F, R, A]): Kleisli[F, R, A] = Kleisli[F, R, A](r => fa.run(f(r)))
}
private trait KleisliHoist[R] extends Hoist[({type λ[α[_], β] = Kleisli[α, R, β]})#λ] {
def hoist[M[_]: Monad, N[_]](f: M ~> N): ({type f[x] = Kleisli[M, R, x]})#f ~> ({type f[x] = Kleisli[N, R, x]})#f =
new (({type f[x] = Kleisli[M, R, x]})#f ~> ({type f[x] = Kleisli[N, R, x]})#f) {
def apply[A](m: Kleisli[M, R, A]): Kleisli[N, R, A] = Kleisli[N, R, A](r => f(m(r)))
}
def liftM[G[_] : Monad, A](a: G[A]): Kleisli[G, R, A] = Kleisli(_ => a)
implicit def apply[G[_] : Monad]: Monad[({type λ[α] = Kleisli[G, R, α]})#λ] = Kleisli.kleisliMonadReader
}
private trait KleisliMonadPlus[F[_], R] extends MonadPlus[({type λ[α] = Kleisli[F, R, α]})#λ] with KleisliPlusEmpty[F, R] with KleisliMonad[F, R] {
implicit def F: MonadPlus[F]
}
private trait KleisliContravariant[F[_], X] extends Contravariant[({type λ[α] = Kleisli[F, α, X]})#λ] {
def contramap[A, B](fa: Kleisli[F, A, X])(f: B => A) = fa local f
}
//
// (* *) -> *
//
private trait KleisliProfunctor[F[_]] extends Profunctor[({type λ[α, β] = Kleisli[F, α, β]})#λ] {
implicit def F: Functor[F]
override def mapfst[A, B, C](fa: Kleisli[F, A, B])(f: C => A) = fa local f
override def mapsnd[A, B, C](fa: Kleisli[F, A, B])(f: B => C) = fa map f
}
private trait KleisliCompose[F[_]] extends Compose[({type λ[α, β] = Kleisli[F, α, β]})#λ] {
implicit def F: Bind[F]
def compose[A, B, C](bc: Kleisli[F, B, C], ab: Kleisli[F, A, B]): Kleisli[F, A, C] = ab >=> bc
}
private trait KleisliArrow[F[_]]
extends Arrow[({type λ[α, β] = Kleisli[F, α, β]})#λ]
with Choice[({type λ[α, β] = Kleisli[F, α, β]})#λ]
with KleisliCompose[F]
with KleisliProfunctor[F] {
implicit def F: Monad[F]
def id[A]: Kleisli[F, A, A] = kleisli(a => F.point(a))
def arr[A, B](f: A => B): Kleisli[F, A, B] = kleisli(a => F.point(f(a)))
def first[A, B, C](f: Kleisli[F, A, B]): Kleisli[F, (A, C), (B, C)] = kleisli[F, (A, C), (B, C)] {
case (a, c) => F.map(f.run(a))((b: B) => (b, c))
}
def choice[A, B, C](f: => Kleisli[F, A, C], g: => Kleisli[F, B, C]): Kleisli[F, A \/ B, C] =
Kleisli {
case -\/(a) => f run a
case \/-(b) => g run b
}
override def split[A, B, C, D](f: Kleisli[F, A, B], g: Kleisli[F, C, D]): Kleisli[F, (A, C), (B, D)] =
Kleisli {
case (a, c) =>
F.bind(f run a)(b => F.map(g run c)(d => (b, d)))
}
}
private trait KleisliSemigroup[F[_], A, B] extends Semigroup[Kleisli[F, A, B]] {
implicit def FB: Semigroup[F[B]]
def append(f1: Kleisli[F, A, B], f2: => Kleisli[F, A, B]) = Kleisli[F, A, B](a => FB.append(f1.run(a), f2.run(a)))
}
private trait KleisliMonoid[F[_], A, B] extends Monoid[Kleisli[F, A, B]] with KleisliSemigroup[F, A, B] {
implicit def FB: Monoid[F[B]]
def zero = Kleisli[F, A, B](a => FB.zero)
}
private trait KleisliPlus[F[_], A] extends Plus[({type λ[α]=Kleisli[F, A, α]})#λ] {
implicit def F: Plus[F]
def plus[B](f1: Kleisli[F, A, B], f2: => Kleisli[F, A, B]) = Kleisli[F, A, B](a => F.plus[B](f1.run(a), f2.run(a)))
}
private trait KleisliPlusEmpty[F[_], A] extends PlusEmpty[({type λ[α]=Kleisli[F, A, α]})#λ] with KleisliPlus[F, A] {
implicit def F: PlusEmpty[F]
def empty[B] = Kleisli[F, A, B](a => F.empty[B])
}
private trait KleisliCatchable[F[_], A] extends Catchable[({type λ[α]=Kleisli[F, A, α]})#λ] {
implicit def F: Catchable[F]
def attempt[B](f: Kleisli[F, A, B]): Kleisli[F, A, Throwable \/ B] =
Kleisli(a => F.attempt(try f.run(a) catch { case t: Throwable => F.fail(t) }))
def fail[B](err: Throwable): Kleisli[F, A, B] = Kleisli(_ => F.fail(err))
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy