package readerwriter.internal import algebra.Monoid import applicative.Monad final case class Writer[L, A](v: (L, A)) object Writer: given [A]: Monoid[List[A]] with def zero: List[Nothing] = List.empty def combine(l1: List[A], l2: List[A]): List[A] = l1 ++ l2 def tell[L](l: L): Writer[L, Unit] = Writer((l, ())) given writerMonad[L: Monoid]: Monad[[a] =>> Writer[L, a]] with def pure[A](a: A): Writer[L, A] = Writer((summon[Monoid[L]].zero, a)) extension [A](fa: Writer[L, A]) def flatMap[B](f: A => Writer[L, B]): Writer[L, B] = val next = f(fa.v._2) Writer((implicitly[Monoid[L]].combine(fa.v._1, next.v._1), next.v._2)) override def map2[B, C](fb: Writer[L, B])(f: (A, B) => C): Writer[L, C] = Writer((implicitly[Monoid[L]].combine(fa.v._1, fb.v._1), f(fa.v._2, fb.v._2))) override def map[B](f: A => B): Writer[L, B] = Writer((fa.v._1, f(fa.v._2)))