Created
May 17, 2018 07:02
-
-
Save regiskuckaertz/334fa76da70dbd4b7d13a58e9d3ee24e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment