Last active
January 17, 2017 11:00
-
-
Save jto/019d41cc8f40ed706de1e0692cfbc953 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Test { | |
import scalaz._, Scalaz._ | |
type FA[F[_], S, A] = FreeAp[λ[α => S => F[(S, α)]], A] | |
type Precepte[F[_], S, A] = Free[({ type L[A] = FA[F, S, A] })#L, A] | |
type UnmanagedState = List[String] | |
trait PreBuilder[F[_]]{ | |
type Pre[A] = Precepte[F, UnmanagedState, A] | |
type St0[A] = UnmanagedState => F[(UnmanagedState, A)] | |
type St[A] = FA[F, UnmanagedState, A] | |
def apply[A](tag: String)(a: A)(implicit ap: Applicative[F]): Pre[A] = { | |
val fap = FreeAp.lift[St0, A] { s => (s, a).point[F] } | |
val p = Free.liftF[St, A](fap) | |
substep(tag)(p) | |
} | |
def suspend[A](tag: String)(fa: => F[A])(implicit ap: Functor[F]): Pre[A] = { | |
val fap = FreeAp.lift[St0, A]{ s => fa.map(s -> _) } | |
val p = Free.liftF[St, A](fap) | |
substep(tag)(p) | |
} | |
def substep[A](tag: String)(p: Pre[A]): Pre[A] = { | |
val go0 = new (St0 ~> St0) { | |
def apply[A](st: St0[A]) = s => st(s :+ tag) | |
} | |
val go = new (St ~> St) { | |
def apply[A](st: St[A]) = st.hoist(go0) | |
} | |
p.mapFirstSuspension(go) | |
} | |
def pure[A](a: A): Pre[A] = | |
Free.pure[St, A](a) | |
} | |
object Precepte { | |
def apply[F[_]] = new PreBuilder[F]{} | |
} | |
implicit def stepApplicative[F[_]: Applicative, S] = | |
new Applicative[λ[α => S => F[(S, α)]]] { | |
def point[A](a: => A): S => F[(S, A)] = | |
s => (s, a).point[F] | |
def ap[A, B](fa: => S => F[(S, A)])(f: => S => F[(S, A => B)]): S => F[(S, B)] = { s0 => | |
val f0 = fa(s0) | |
val f1 = f(s0) | |
(f0 |@| f1) { (a, b) => | |
(a._1, b._2(a._2)) // XXX: idiotic state management | |
} | |
} | |
} | |
def runAp[F[_], S](implicit A: Applicative[λ[α => S => F[(S, α)]]]) = | |
new (FA[F, S, ?] ~> λ[α => S => F[(S, α)]]) { | |
def apply[A](fa: FA[F, S, A]): S => F[(S, A)] = { | |
val refl = NaturalTransformation.refl[λ[α => S => F[(S, α)]]] | |
fa.foldMap[λ[α => S => F[(S, α)]]](refl) | |
} | |
} | |
implicit def mo[F[_]: Monad, S] = | |
new Monad[λ[α => S => F[(S, α)]]] { | |
def point[A](a: => A) = s => (s, a).point[F] | |
def bind[A, B](oa: S => F[(S, A)])(f: A => (S => F[(S, B)])): S => F[(S, B)] = | |
s0 => oa(s0).flatMap { case (s1, a) => f(a)(s1) } | |
} | |
import akka.pattern.after | |
import scala.concurrent.ExecutionContext.Implicits.global | |
import scala.concurrent.Future | |
import scala.concurrent.duration._ | |
import akka.actor.ActorSystem | |
val system = ActorSystem("theSystem") | |
def f1 = after(duration = 10 second, using = system.scheduler)({println(System.currentTimeMillis); 1}.point[Future]) | |
def f2 = after(duration = 10 second, using = system.scheduler)({println(System.currentTimeMillis); 2}.point[Future]) | |
def go[F[_]: Monad](f1: => F[Int], f2: => F[Int]): UnmanagedState => F[(UnmanagedState, (Int, Int))] = { | |
import scalaz.syntax.applicative._ | |
type Pre[A] = Precepte[F, UnmanagedState, A] | |
val p1: Pre[Int] = Precepte[F].suspend("p1")(f1) | |
val p2: Pre[Int] = Precepte[F].suspend("p2")(f2) | |
val p3: Pre[Int] = Precepte[F].substep("p3")(p1.flatMap(r1 => p2.map(r2 => r1 + r2))) | |
val nostate: UnmanagedState = Nil | |
type S0[α] = FA[F, UnmanagedState, α] | |
// implicit val freeMonad = Free.freeMonad[S0] | |
// implicit val freeAp = stepApplicative[Future, UnmanagedState] | |
// // p3.foldMap(run[S0]) // (List("p3", "p1", "p2"), 3) | |
(p1 |@| p2).tupled.foldMap[λ[α => UnmanagedState => F[(UnmanagedState, α)]]](runAp) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment