-
-
Save lshoo/004cf9d70d1feadf39ffa1002fb71b60 to your computer and use it in GitHub Desktop.
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) |
build.sbt:
name := "learncats"
version := "1.0"
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
"org.typelevel" %% "cats" % "0.6.0",
"com.chuusai" %% "shapeless" % "2.2.5",
"org.typelevel" %% "shapeless-scalacheck" % "0.4",
"org.typelevel" %% "shapeless-spire" % "0.4",
"ch.qos.logback" % "logback-classic" % "1.0.13",
"postgresql" % "postgresql" % "9.1-901.jdbc4",
"com.jolbox" % "bonecp" % "0.8.0.RELEASE"
)
scalacOptions += "-feature"
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)
抄的http://typelevel.org/cats/tut/freemonad.html
![image](https://cloud.githubusercontent.com/assets/670440/16144363/06adeee6-34a5-11e6-8f69-13e67d76335e.png)
但52行的kvs.get(key).map(_.asInstanceOf[A]