Last active
September 9, 2017 04:27
-
-
Save animatedlew/3c12ec86741b15a68f23a92b51428775 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
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