Skip to content

Instantly share code, notes, and snippets.

@animatedlew
Last active September 9, 2017 04:27
Show Gist options
  • Save animatedlew/3c12ec86741b15a68f23a92b51428775 to your computer and use it in GitHub Desktop.
Save animatedlew/3c12ec86741b15a68f23a92b51428775 to your computer and use it in GitHub Desktop.
import cats.~>
import cats.free._, Free._
import cats.instances.option._
// ADT
sealed trait Moves[A]
case class MoveUp[A: Numeric](pace: A) extends Moves[A]
case class MoveDown[A: Numeric](pace: A) extends Moves[A]
case class MoveRight[A: Numeric](pace: A) extends Moves[A]
case class MoveLeft[A: Numeric](pace: A) extends Moves[A]
case object PenDown extends Moves[Unit]
case object PenUp extends Moves[Unit]
// create Free[_] based on moves
type Command[A] = Free[Moves, A]
// create smart constructors for moves using liftF
def moveUp[A: Numeric](pace: A): Command[A] = liftF(MoveUp(pace))
def moveDown[A: Numeric](pace: A): Command[A] = liftF(MoveDown(pace))
def moveLeft[A: Numeric](pace: A): Command[A] = liftF(MoveLeft(pace))
def moveRight[A: Numeric](pace: A): Command[A] = liftF(MoveRight(pace))
def penDown: Command[Unit] = liftF(PenDown)
def penUp: Command[Unit] = liftF(PenUp)
// build programs
def program1 = for {
_ <- moveDown(20)
_ <- penDown
a <- moveDown(20)
b <- moveRight(20)
c <- moveUp(20)
d <- moveLeft(20)
_ <- penUp
} yield a + b + c + d
def program2 = for {
_ <- penDown
a <- moveLeft(20)
b <- moveDown(20)
_ <- penUp
} yield a + b
def program: Free[Moves, Int] = for {
a <- program1
b <- program2
} yield a + b
// build a compiler
val compiler = new (Moves ~> Option) {
def apply[A](fa: Moves[A]): Option[A] =
fa match {
case MoveUp(n) =>
println("up")
Some(n)
case MoveDown(n) =>
println("down")
Some(n)
case MoveLeft(n) =>
println("left")
Some(n)
case MoveRight(n) =>
println("right")
Some(n)
case PenDown =>
println("pen down")
Some(().asInstanceOf[A])
case PenUp =>
println("pen up")
Some(().asInstanceOf[A])
case _ =>
println("error")
None
}
}
// run the program
program.foldMap(compiler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment