Skip to content

Instantly share code, notes, and snippets.

@dorsev
Created March 25, 2019 10:01
Show Gist options
  • Save dorsev/4eec40a62271a31433d778a9262bef7f to your computer and use it in GitHub Desktop.
Save dorsev/4eec40a62271a31433d778a9262bef7f to your computer and use it in GitHub Desktop.
package sandbox
import cats.free.Free
import cats.implicits._
object FreeMonadExample extends App {
sealed trait KvStoreA[A]
case class Put[A](key: String, value: A) extends KvStoreA[Unit]
case class Get[A](key: String) extends KvStoreA[Option[A]]
case class Delete[A](key: String) extends KvStoreA[Unit]
type KvStore[A] = Free[KvStoreA, A]
import cats.free.Free.liftF
def put[T](key: String, value: T): KvStore[Unit] =
liftF[KvStoreA, Unit](Put[T](key, value))
def get[T](key: String): KvStore[Option[T]] =
liftF[KvStoreA, Option[T]](Get(key))
def delete[T](key: String): KvStore[Unit] =
liftF[KvStoreA, Unit](Delete(key))
def update[T](key: String, f: T => T): KvStore[Unit] =
for {
vMaybe <- get[T](key)
_ <- vMaybe.map(v => put[T](key, f(v))).getOrElse(Free.pure(()))
} yield ()
def program: Free[KvStoreA, Option[Int]] = {
for {
_ <- put("wild-cats", 2)
_ <- update[Int]("wild-cats", _ + 12)
_ <- put("tame-cats", 5)
n <- get[Int]("wild-cats")
_ <- delete("tame-cats")
} yield n
}
import cats.arrow.FunctionK
import cats.{Id, ~>}
import scala.collection.mutable
def impureCompiler: KvStoreA ~> Id = new (KvStoreA ~> Id) {
val kvs = mutable.Map.empty[String, Any]
override def apply[A](fa: KvStoreA[A]): Id[A] = {
fa match {
case Put(key, value) =>
println(s"put($key, $value)")
kvs(key) = value
()
case Get(key) =>
println(s"get($key)")
kvs.get(key).map(_.asInstanceOf[A])
case Delete(key) =>
println(s"delete($key)")
kvs.remove(key)
()
}
}
}
val result: Option[Int] = program.foldMap(impureCompiler)
println(result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment