Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package example
- import cats._
- import cats.free._
- import cats.data._
- import cats.syntax.flatMap._
- import cats.effect.{LiftIO, IO}
- object Example {
- import functors._
- import stacks._
- import cats.data.Tuple2K._
- type Effect[A] = EitherK[Logging, Persist, A]
- type Interp[A] = Tuple2K[CoLogging, CoPersist, A]
- def prog(implicit L: Logs[Effect], P: Persists[Effect]): Free[Effect, Unit] =
- P.store("bar") >> L.log("foo")
- def interpretEffect(implicit CL: CoLogs[IO], CP: CoPersists[IO]): Cofree[Interp, IO[Unit]] =
- Cofree.unfold(IO.pure(())) { a: IO[Unit] => Tuple2K(CoLogging(CL.coLog(a)), CoPersist(CP.coPersist(a))) }
- }
- /////////////////// FREE STUFF
- case class Logging[A](msg: String, action: A)
- case class Persist[A](msg: String, action: A)
- class Logs[F[_]](implicit I: InjectK[Logging, F]) {
- def log(msg: String): Free[F, Unit] = Free.inject[Logging, F](Logging(msg, ()))
- }
- class Persists[F[_]](implicit I: InjectK[Persist, F]) {
- def store(msg: String): Free[F, Unit] = Free.inject[Persist, F](Persist(msg, ()))
- }
- /////////////////// COFREE STUFF
- case class CoLogging[A](run: String => A)
- case class CoPersist[A](run: String => A)
- class CoLogs[F[_]: FlatMap](implicit L: LiftIO[F]) {
- def coLog(f: F[Unit])(msg: String): F[Unit] = f >> L.liftIO(IO {
- println(msg)
- })
- }
- class CoPersists[F[_]: FlatMap](implicit L: LiftIO[F]) {
- def coPersist(f: F[Unit])(msg: String): F[Unit] = f >> L.liftIO(IO {
- println(s"storing $msg")
- })
- }
- /////////////////// TYPECLASS INSTANCES
- object functors {
- implicit val fLogging = new Functor[Logging] {
- def map[A, B](fa: Logging[A])(f: A => B) = Logging(fa.msg, f(fa.action))
- }
- implicit val fPersist = new Functor[Persist] {
- def map[A, B](fa: Persist[A])(f: A => B) = Persist(fa.msg, f(fa.action))
- }
- implicit val fCoLogging = new Functor[CoLogging] {
- def map[A, B](fa: CoLogging[A])(f: A => B) = CoLogging(fa.run andThen f)
- }
- implicit val fCoPersist = new Functor[CoPersist] {
- def map[A, B](fa: CoPersist[A])(f: A => B) = CoPersist(fa.run andThen f)
- }
- }
- object stacks {
- implicit def liftCoLogs[F[_]: FlatMap](implicit L: LiftIO[F]) = new CoLogs[F]
- implicit def liftCoPersists[F[_]: FlatMap](implicit L: LiftIO[F]) = new CoPersists[F]
- implicit def liftLogging[F[_]](implicit I: InjectK[Logging, F]) = new Logs[F]
- implicit def liftPersist[F[_]](implicit I: InjectK[Persist, F]) = new Persists[F]
- }
Add Comment
Please, Sign In to add comment