Skip to content

Instantly share code, notes, and snippets.

@mmenestret
Last active September 14, 2018 09:16
Show Gist options
  • Save mmenestret/09796f1de242bcf881b0089b484f2abd to your computer and use it in GitHub Desktop.
Save mmenestret/09796f1de242bcf881b0089b484f2abd to your computer and use it in GitHub Desktop.
Creation of a MonadT for Log
case class LoggingT[F[_], A](
run: List[String] => F[(List[String], A)]) { self =>
def map[B](f: A => B)(implicit F: Functor[F]): LoggingT[F, B] =
LoggingT[F, B](log => self.run(log).map(t => (t._1, f(t._2))))
def flatMap[B](f: A => LoggingT[F, B])(implicit F: Monad[F]): LoggingT[F, B] =
LoggingT[F, B](log => self.run(log).flatMap(t => f(t._2).run(t._1)))
def eval(implicit F: Functor[F]): F[(List[String], A)] = run(Nil).map(t => (t._1.reverse, t._2))
}
object LoggingT {
def point[F[_]: Applicative, A](a: => A): LoggingT[F, A] = LoggingT(log => Applicative[F].point((log, a)))
def lift[F[_], A](fa: F[A])(implicit F: Functor[F]): LoggingT[F, A] =
LoggingT(log => fa.map(a => (log, a)))
implicit def LoggingTMonad[F[_]: Monad]: Monad[LoggingT[F, ?]] =
???
def log[F[_]: Applicative](line: String): LoggingT[F, Unit] =
LoggingT(log => Applicative[F].point((line :: log, ())))
}
def getName[F[_]: Console: Monad]: F[String] =
(for {
_ <- LoggingT.lift[F, Unit](Console.putStrLn("Hello, what is your name?"))
_ <- LoggingT.log[F]("My log line")
n <- LoggingT.lift[F, String](Console.getStrLn)
_ <- LoggingT.lift[F, Unit](Console.putStrLn("Good to meet you, " + n + "!"))
} yield n).eval.flatMap {
case (log, name) =>
val lines = log.mkString("\n")
Console.putStrLn(s"Logging: \n${lines}").map(_ => name)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment