Skip to content

Instantly share code, notes, and snippets.

@ceedubs
Created December 6, 2014 17:34
Show Gist options
  • Save ceedubs/510a7eb9147c9d27132c to your computer and use it in GitHub Desktop.
Save ceedubs/510a7eb9147c9d27132c to your computer and use it in GitHub Desktop.
Using WriterT for logging of Random => IO[A]
object WriterTExample extends App {
import scalaz._
import scalaz.effect.IO
import scala.util.Random
import scalaz.syntax.monad._
type Logged[F[_], A] = WriterT[F, DList[String], A]
def log[F[_]](msg: => String)(implicit F: Applicative[F]): Logged[F, Unit] =
WriterT.writerT(F.point(DList(msg), ()))
/** A random number generator reader can take an instance of Random as input
* and run a side effect to produce a result */
type RngReader[A] = Kleisli[IO, Random, A]
type LoggedR[A] = Logged[RngReader, A]
/** log helper with the type parameter fixed to LoggedR */
def logR(msg: => String): LoggedR[Unit] =
log(msg)
def randomInt(below: Int): RngReader[Int] =
Kleisli(rng => IO(rng.nextInt(below)))
val addTwoRandomInt: LoggedR[Int] = for {
_ <- logR("start")
first <- randomInt(10).liftM[Logged]
_ <- logR(s"initialized first: $first")
second <- randomInt(10).liftM[Logged]
_ <- logR(s"initialized second: $second")
_ <- logR("finish")
} yield first + second
val appOutput: RngReader[String] =
addTwoRandomInt.run.map{ case (logs, sum) =>
(logs :+ s"sum: $sum").toList.mkString("\n")
}
val app: IO[Unit] = for {
rng <- IO(new Random())
output <- appOutput(rng)
_ <- IO(println(output))
} yield ()
app.unsafePerformIO()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment