|
Scala example source code file (FreeAp.scala)
The FreeAp.scala Scala example source codepackage scalaz /** * Free applicative functors. Less expressive than free monads, but more * flexible to inspect and interpret. */ sealed abstract class FreeAp[F[_],A] { import FreeAp._ /** * The canonical natural transformation that interprets this free * program by giving it the semantics of the applicative functor `G`. * Not tail-recursive unless `G` is a free monad. */ def foldMap[G[_]:Applicative](f: F ~> G): G[A] = this match { case Pure(x) => Applicative[G].pure(x) case x@Ap() => Applicative[G].ap(f(x.v()))(x.k() foldMap f) } /** Provides access to the first instruction of this program, if present */ def para[B](pure: A => B, ap: λ[α => (F[α], FreeAp[F, α => A])] ~> λ[α => B]): B = this match { case Pure(x) => pure(x) case x@Ap() => ap(x.v() -> x.k()) } /** * Performs a monoidal analysis over this free program. Maps the * effects in `F` to values in the monoid `M`, discarding the values * of those effects. * Example: * * {{{ * def count[F[_],B](p: FreeAp[F,B]): Int = * p.analyze(new (F ~> λ[α => Int]) { * def apply[A](a: F[A]) = 1 * }) * }}} */ def analyze[M:Monoid](f: F ~> λ[α => M]): M = foldMap[Const[M, ?]](new (F ~> Const[M, ?]) { def apply[X](x: F[X]): Const[M,X] = Const(f(x)) }).getConst /** * The natural transformation from `FreeAp[F,_]` to `FreeAp[G,_]` */ def hoist[G[_]](f: F ~> G): FreeAp[G,A] = this match { case Pure(a) => Pure(a) case x@Ap() => FreeAp(f(x.v()), x.k() hoist f) } /** * Interprets this free `F` program using the semantics of the * `Applicative` instance for `F`. */ def retract(implicit F: Applicative[F]): F[A] = this match { case Pure(a) => Applicative[F].pure(a) case x@Ap() => Applicative[F].ap(x.v())(x.k().retract) } /** * Embeds this program in the free monad on `F`. */ def monadic: Free[F,A] = foldMap[Free[F,?]](new (F ~> Free[F,?]) { def apply[B](fb: F[B]) = Free.liftF(fb) }) /** Idiomatic function application */ def ap[B](f: FreeAp[F, A => B]): FreeAp[F,B] = f match { case Pure(g) => map(g) case x@Ap() => FreeAp(x.v(), ap(x.k().map(g => (a:A) => (b:x.I) => g(b)(a)))) } /** Append a function to the end of this program */ def map[B](f: A => B): FreeAp[F,B] = this match { case Pure(a) => Pure(f(a)) case x@Ap() => FreeAp(x.v(), x.k().map(f compose _)) } } object FreeAp { implicit def freeInstance[F[_]]: Applicative[FreeAp[F, ?]] = new Applicative[FreeAp[F, ?]] { def point[A](a: => A) = FreeAp.point(a) def ap[A,B](fa: => FreeAp[F,A])(ff: => FreeAp[F, A => B]) = fa ap ff } /** Return a value in a free applicative functor */ def point[F[_],A](a: A): FreeAp[F,A] = Pure(a) /** Return a value in a free applicative functor. Alias for `point`. */ def pure[F[_],A](a: A): FreeAp[F,A] = point(a) /** Lift a value in `F` into the free applicative functor on `F` */ def lift[F[_],A](x: => F[A]): FreeAp[F, A] = FreeAp(x, Pure((a: A) => a)) /** A version of `lift` that infers the nested type constructor. */ def liftU[FA](x: => FA)(implicit FA: Unapply[Functor, FA]): FreeAp[FA.M, FA.A] = lift(FA(x)) private [scalaz] case class Pure[F[_],A](a: A) extends FreeAp[F,A] private abstract case class Ap[F[_],A]() extends FreeAp[F,A] { type I val v: () => F[I] val k: () => FreeAp[F, I => A] } /** * Add an effect to the front of a program that produces a continuation for it. */ def apply[F[_],A,B](value: => F[A], function: => FreeAp[F, A => B]): FreeAp[F,B] = new Ap[F,B] { type I = A val v = () => value val k = () => function } } Other Scala examples (source code examples)Here is a short list of links related to this Scala FreeAp.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.