Last active
October 5, 2017 00:19
-
-
Save conniec/c53b93127b606a8af39f to your computer and use it in GitHub Desktop.
Free Monad example with Cats and Scalaz
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
import cats.free.Free | |
import cats.~> | |
import cats._, cats.std.all._ | |
import cats.Functor | |
// https://github.com/non/cats/blob/master/docs/src/main/tut/freemonad.md | |
sealed trait Command[+Next] | |
case class Person(name: String) extends AnyVal | |
case class Push[Next](person: Person, next: Next) extends Command[Next] | |
case class Pop[Next](onResult: Person => Next) extends Command[Next] | |
object CatsFreeMonadExample { | |
implicit val functor: Functor[Command] = new Functor[Command] { | |
def map[A, B](fa: Command[A])(f: A => B): Command[B] = fa match { | |
case Push(p, next) => Push(p, f(next)) | |
case Pop(next) => { | |
def func(person: Person): B = f(next(person)) | |
Pop(func) | |
} | |
} | |
} | |
def push(p: Person): Free[Command, Unit] = Free.liftF(Push(p, ())) | |
def pop: Free[Command, Person] = Free.liftF(Pop(identity)) | |
val logic: Free[Command, Person] = for { | |
_ <- push(Person("Alice")) | |
_ <- push(Person("Bob")) | |
person <- pop | |
} yield person | |
var stack = Seq.empty[Person] | |
val invoker = new (Command ~> Id) { | |
override def apply[A](e: Command[A]): Id[A] = e match { | |
case Push(p, next) => { | |
stack = Seq(p) ++ stack | |
println(s"put $p") | |
next | |
} | |
case Pop(next) => { | |
val head = stack.head | |
println(s"pop $head") | |
stack = stack.tail | |
next(head) | |
} | |
} | |
} | |
// To run the logic with invoker | |
val result = logic.foldMap(invoker) | |
println(result) | |
} |
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
import scalaz.Free | |
import scalaz._ | |
import scalaz.syntax._ | |
import scalaz.std.list._ | |
import scalaz.syntax.traverse._ | |
// http://eed3si9n.com/learning-scalaz/Free+Monad.html | |
sealed trait Command[+Next] | |
case class Person(name: String) extends AnyVal | |
case class Push[Next](person: Person, next: Next) extends Command[Next] | |
case class Pop[Next](onResult: Person => Next) extends Command[Next] | |
object ScalazFreeMonadExample { | |
implicit val commandFunctor: Functor[Command] = new Functor[Command] { | |
def map[A, B](fa: Command[A])(f: A => B): Command[B] = fa match { | |
case Push(p, next) => Push[B](p, f(next)) | |
case Pop(next) => { | |
def func(person: Person): B = f(next(person)) | |
Pop[B](func) | |
} | |
} | |
} | |
def push(p: Person): Free[Command, Unit] = Free.liftF(Push(p, ())) // Next is Unit | |
def pop: Free[Command, Person] = Free.liftF(Pop(identity)) // Next is Person | |
val logic: Free[Command, Person] = for { | |
_ <- push(Person("Alice")) | |
_ <- push(Person("Bob")) | |
person <- pop | |
} yield person | |
var stack = Seq.empty[Person] | |
def invoker[A](p: Free[Command, A]): A = { | |
p.resume.fold({ | |
case Push(p, next) => { | |
stack = Seq(p) ++ stack | |
invoker(next) | |
} | |
case Pop(next) => { | |
val head = stack.head | |
println(s"pop $head") | |
stack = stack.tail | |
invoker(next(head)) | |
} | |
}, | |
{r: A => r}) | |
} | |
// To run the logic with invoker | |
val result = invoker(logic) | |
println(result) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment