Skip to content

Instantly share code, notes, and snippets.

@lshoo
Created June 17, 2016 08:01
Show Gist options
  • Save lshoo/004cf9d70d1feadf39ffa1002fb71b60 to your computer and use it in GitHub Desktop.
Save lshoo/004cf9d70d1feadf39ffa1002fb71b60 to your computer and use it in GitHub Desktop.
cats Free monad tutorial
sealed trait KVStoreA[A]
case class Put[A](key: String, value: A) extends KVStoreA[Unit]
case class Get[A](key: String) extends KVStoreA[A]
case class Delete(key: String) extends KVStoreA[Unit]
import cats.free.Free
type KVStore[A] = Free[KVStoreA, A]
import cats.free.Free.liftF
def put[T](key: String, value: T): KVStore[Unit] = liftF[KVStoreA, Unit](Put(key, value))
def get[T](key: String): KVStore[Option[T]] = liftF[KVStoreA, Option[T]](Get(key))
def delete(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 ()
// 3. Build a program
val key1 = "wild-cats"
val key2 = "tame-cats"
def program: KVStore[Option[Int]] = for {
_ <- put(key1, 2)
_ <- update[Int](key1, (_ + 3))
_ <- put(key2, 5)
n <- get[Int](key1)
_ <- delete(key2)
} yield n
import cats.arrow.NaturalTransformation
import cats.{Id, ~>}
import scala.collection.mutable
def impureCompiler: KVStoreA ~> Id =
new (KVStoreA ~> Id) {
// a very simple (and imprecise) key-value store
val kvs = mutable.Map.empty[String, Any]
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)
@Bayakala
Copy link

Bayakala commented Jun 17, 2016

sealed trait KVStoreA[A]
case class Put[A](key: String, value: A) extends KVStoreA[Unit]
case class Get[A](key: String) extends KVStoreA[A]
case class Delete(key: String) extends KVStoreA[Unit]

import cats.free.Free
type KVStore[A] = Free[KVStoreA, A]

import cats.free.Free.liftF

def put[T](key: String, value: T): KVStore[Unit] = liftF[KVStoreA, Unit](Put%28key, value%29)

def get[T](key: String): KVStore[Option[T]] = liftFKVStoreA, Option[T]

def delete(key: String): KVStore[Unit] = liftFKVStoreA, Unit

def update[T](key: String, f: T => T): KVStore[Unit] = for {
vMaybe <- getT
_ <- vMaybe.map(v => put[T](key, f%28v%29)).getOrElse(Free.pure(()))
} yield ()

// 3. Build a program
val key1 = "wild-cats"
val key2 = "tame-cats"
def program: KVStore[Option[Int]] = for {
_ <- put(key1, 2)
_ <- update[Int](key1, %28_ + 3%29)
_ <- put(key2, 5)
n <- getInt
_ <- delete(key2)
} yield n
import cats.arrow.NaturalTransformation
import cats.{Id, ~>}
import scala.collection.mutable
def impureCompiler: KVStoreA ~> Id =
new (KVStoreA ~> Id) {

// a very simple (and imprecise) key-value store
val kvs = mutable.Map.empty[String, Any]

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]).getOrElse(null.asInstanceOf[A])
    case Delete(key) =>
      println(s"delete($key)")
      kvs.remove(key)
      ()
  }

}
val result: Option[Int] = program.foldMap(impureCompiler)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment