Skip to content

Instantly share code, notes, and snippets.

@Baccata
Last active November 16, 2016 11:29
Show Gist options
  • Save Baccata/dd6bed5246a24976c9a45507e9bb899a to your computer and use it in GitHub Desktop.
Save Baccata/dd6bed5246a24976c9a45507e9bb899a to your computer and use it in GitHub Desktop.
import cats.free.Free
import cats.{ Monad, ~> }
object KVStoreExample {
sealed trait KVStore[A]
case class Put[T](key: String, value: T) extends KVStore[Unit]
case class Get[T](key: String) extends KVStore[Option[T]]
object KVStore {
trait Interface[M[_]] {
def put[T](key: String, value: T): M[Unit]
def get[T](key: String): M[Option[T]]
}
trait Interp[M[_]] extends (KVStore ~> M) with Interface[M] {
def run[A](f: Free[KVStore, A])(implicit monad: Monad[M]): M[A] =
f.foldMap(this)
}
object Interp {
def fromArrow[M[_]](arrow: KVStore ~> M): Interp[M] =
new ReverseRoutedInterp[M](arrow)
}
//User has to implement the methods
trait RoutedInterp[M[_]] extends Interp[M] {
override final def apply[A](fa: KVStore[A]): M[A] = fa match {
case Put(key, value) => put(key, value)
case Get(key) => get(key)
}
}
//User has to construct using an arrow
case class ReverseRoutedInterp[M[_]](underlying: KVStore ~> M)
extends Interp[M] {
override final def put[T](key: String, value: T): M[Unit] =
apply(Put(key, value))
override final def get[T](key: String): M[Option[T]] = apply(Get(key))
override final def apply[A](fa: KVStore[A]): M[A] = underlying.apply(fa)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment