Writer

case class Writer[A, W](a: A, w: W)

object Writer {

  import Monoid.MonoidOps

  implicit def readerMonad[W:Monoid]: Monad[({ type λ[ɑ] = Writer[ɑ,W] })#λ] =
    new Monad[({ type λ[ɑ] = Writer[ɑ,W] })#λ] {

      def pure[A](a: A): Writer[A,W] =
        Writer(a, implicitly[Monoid[W]].mempty)

      def flatMap[A,B](ma: Writer[A,W])(f: A => Writer[B,W]): Writer[B,W] = {
        val mb: Writer[B,W] = f(ma.a)
        val b: B = mb.a
        val w: W = ma.w <#> mb.w
        Writer(b, w)
      }
    }
}