Skip to content

Instantly share code, notes, and snippets.

@gabro
Last active September 24, 2015 10:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabro/bf5d6918303a0118e21e to your computer and use it in GitHub Desktop.
Save gabro/bf5d6918303a0118e21e to your computer and use it in GitHub Desktop.
Learning the Free monad with cats
package project
import cats._
import cats.free.Free
object Main extends App {
import Algebra._
import ConsultationOp._
val c = Consultation(_id = "123", title = "A consultation")
val res = for {
_ <- create(c)
_ <- get("124")
c <- get(c._id)
} yield c
println(res)
res.foldMap(MockInterpreter)
}
object Algebra {
type ConsultationId = String
case class Consultation(_id: ConsultationId, title: String)
sealed trait ConsultationOp[A]
object ConsultationOp {
case class Create(c: Consultation) extends ConsultationOp[Unit]
case class Get(s: ConsultationId) extends ConsultationOp[Option[Consultation]]
}
def create(c: Consultation) =
Free.liftF[ConsultationOp, Unit](ConsultationOp.Create(c))
def get(id: ConsultationId) =
Free.liftF[ConsultationOp, Option[Consultation]](ConsultationOp.Get(id))
}
object MockInterpreter extends (Algebra.ConsultationOp ~> Id) {
import Algebra._
import ConsultationOp._
// the "db"
var c: Option[Consultation] = None
def apply[A](in: ConsultationOp[A]): Id[A] =
in match {
case Create(a) =>
// storing it in the "db"
c = Some(a)
println(s"Creating consultation $a")
case Get(id) =>
println(s"Getting consultation with id: $id")
val r = c.filter(_._id == id)
r match {
case Some(r) => println(s"Found consultation $c")
case None => println("Consultation not found")
}
r
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment