Skip to content

Instantly share code, notes, and snippets.

@lshoo
Created June 17, 2016 08:01
Show Gist options
  • Select an option

  • Save lshoo/004cf9d70d1feadf39ffa1002fb71b60 to your computer and use it in GitHub Desktop.

Select an option

Save lshoo/004cf9d70d1feadf39ffa1002fb71b60 to your computer and use it in GitHub Desktop.

Revisions

  1. lshoo created this gist Jun 17, 2016.
    60 changes: 60 additions & 0 deletions scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    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)