The writer effect allows for the accumulation of values, which can be obtained once the program is interpreted.

The writer effect supports parameterization to any type that supports monoidal accumulation while remaining type safe throughout the program declaration.

There needs to be implicit evidence of cats.mtl.FunctorTell[M, W] and Monad[M] for any runtime M[_] used in its interpretation due to the constraints placed by this effect.

The writer effect comes with two operations writer and tell.


writer sets a tuple with the current accumulator value and returning value:

import freestyle.free._
// import freestyle.free._

import freestyle.free.implicits._
// import freestyle.free.implicits._

import freestyle.free.effects.writer
// import freestyle.free.effects.writer

import cats.data.Writer
// import cats.data.Writer

import cats.implicits._
// import cats.implicits._

import cats.mtl.implicits._
// import cats.mtl.implicits._

val wr = writer[List[Int]]
// wr: freestyle.free.effects.writer.AccumulatorProvider[List[Int]] = freestyle.free.effects.writer$AccumulatorProvider@6a2afe6c

import wr.implicits._
// import wr.implicits._

type Logger[A] = Writer[List[Int], A]
// defined type alias Logger

def programWriter[F[_]: wr.WriterM] =
  for {
    _ <- FreeS.pure(1)
    b <- wr.WriterM[F].writer((Nil, 1))
    _ <- FreeS.pure(1)
  } yield b
// programWriter: [F[_]](implicit evidence$1: wr.WriterM[F])cats.free.Free[[β$0$]cats.free.FreeApplicative[F,β$0$],Int]

// res0: cats.Id[(List[Int], Int)] = (List(),1)


tell appends a value for monoidal accumulation:

def programTell[F[_]: wr.WriterM] =
  for {
    _ <- FreeS.pure(1)
    b <- wr.WriterM[F].writer((List(1), 1))
    c <- wr.WriterM[F].tell(List(1))
    _ <- FreeS.pure(1)
  } yield b
// programTell: [F[_]](implicit evidence$1: wr.WriterM[F])cats.free.Free[[β$0$]cats.free.FreeApplicative[F,β$0$],Int]

// res1: cats.Id[(List[Int], Int)] = (List(1, 1),1)