package readerwriter.internal import algebra.Monoid import applicative.Monad final case class Writer[L, A](v: (L, A)) object Writer { implicit def listMonoid[A]: Monoid[List[A]] = new Monoid[List[A]] { def zero: List[Nothing] = List.empty def op(l1: List[A], l2: List[A]): List[A] = l1 ++ l2 } def tell[L](l: L): Writer[L, Unit] = Writer((l, ())) implicit def writerM[L: Monoid]: Monad[Writer[L, ?]] = new Monad[Writer[L, ?]] { override def flatMap[A, B](fa: Writer[L, A])(f: A => Writer[L, B]): Writer[L, B] = { val next = f(fa.v._2) Writer((implicitly[Monoid[L]].op(fa.v._1, next.v._1), next.v._2)) } def unit[A](a: A): Writer[L, A] = Writer((implicitly[Monoid[L]].zero, a)) override def map2[A, B, C](fa: Writer[L, A], fb: Writer[L, B])(f: (A, B) => C): Writer[L, C] = Writer((implicitly[Monoid[L]].op(fa.v._1, fb.v._1), f(fa.v._2, fb.v._2))) override def map[A, B](fa: Writer[L, A])(f: A => B): Writer[L, B] = Writer((fa.v._1, f(fa.v._2))) } }