Created
August 14, 2020 06:56
-
-
Save sir-wabbit/12399a6be52ddfbecd56be18bf0c4257 to your computer and use it in GitHub Desktop.
This file contains 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
sealed trait Free[+F[_], A] | |
object Free { | |
def eval[F[_], A](fa: Free[F, A])(implicit F: Monad[F]): F[A] = { | |
type State = (Free[F, Any], List[Any => Free[F, Any]]) | |
def go(s: State): F[Either[State, Any]] = s match { | |
case (current, stack) => | |
current match { | |
case Done(a) => | |
stack match { | |
case Nil => | |
F.pure(Right(a)) | |
case f :: fs => | |
F.pure(Left(f(a) -> fs)) | |
} | |
case current: Suspend[F, a] => | |
stack match { | |
case Nil => | |
F.map(current.fa)(a => Right(a)) | |
case f :: fs => | |
F.map(current.fa)(a => Left(f(a) -> fs)) | |
} | |
case current: FlatMap[F, a, b] => | |
F.pure(Left(current.fa.asInstanceOf[Free[F, Any]] -> (current.f.asInstanceOf[Any => Free[F, Any]] :: stack))) | |
} | |
} | |
F.tailRecM((fa.asInstanceOf[Free[F, Any]], Nil) : State)(go _).asInstanceOf[F[A]] | |
} | |
final case class Done[A](a: A) extends Free[Nothing, A] | |
final case class Suspend[F[_], A](fa: F[A]) extends Free[F, A] | |
final case class FlatMap[F[_], A, B](fa: Free[F, A], f: A => Free[F, B]) extends Free[F, B] | |
def pure[F[_], A](a: A): Free[F, A] = Done(a) | |
def roll[F[_], A](fa: F[Free[F, A]]): Free[F, A] = | |
FlatMap[F, Free[F, A], A](Suspend(fa), x => x) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment