Skip to content

Instantly share code, notes, and snippets.

@ceedubs
Created December 7, 2014 23:18
Show Gist options
  • Save ceedubs/691389e7700f73a2af7f to your computer and use it in GitHub Desktop.
Save ceedubs/691389e7700f73a2af7f to your computer and use it in GitHub Desktop.
An app that does some logging and adds two random Ints like https://gist.github.com/ceedubs/510a7eb9147c9d27132c except using FreeC
object FreeCTwoRandomIntExample extends App {
import scalaz._
import scalaz.effect.IO
import scala.util.Random
sealed trait Action[A]
final case class Log(msg: String) extends Action[Unit]
final case class RandomInt(below: Int) extends Action[Int]
def log(msg: String) = Free.liftFC(Log(msg))
def randomInt(below: Int) = Free.liftFC(RandomInt(below))
val addTwoRandomInt = for {
_ <- log("start")
first <- randomInt(10)
_ <- log(s"initialized first: $first")
second <- randomInt(10)
_ <- log(s"initialized second: $second")
_ <- log("finish")
} yield first + second
type RngReader[A] = Kleisli[IO, Random, A]
val actionToRngReader = new (Action ~> RngReader) {
def apply[A](action: Action[A]) = action match {
case Log(msg) => Kleisli(_ => IO(println(msg)))
case RandomInt(below) => Kleisli(rng => IO(rng.nextInt(below)))
}
}
val app = Free.runFC(addTwoRandomInt)(actionToRngReader)
val main: IO[Unit] = for {
rng <- IO(new Random())
sum <- app.run(rng)
_ <- IO(println(s"sum: $sum"))
} yield ()
main.unsafePerformIO()
// example output:
// start
// initialized first: 7
// initialized second: 6
// finish
// sum: 13
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment