writer package:capability

writer @tag (a, w) lifts a pure writer action (a, w) to a monadic action in an arbitrary monad m with capability HasWriter. Appends w to the output of the writer capability tag and returns the value a.
Defines a capability type class for writer effects. A writer program can output values with tell. The values output by two consecutive sub-computation are combined using a monoid's mappend. The interface of HasWriter follows that of MonadWriter. However, this module does not include a strategy to provide a HasWriter capability from a MonadWriter instance. It is generally a bad idea to use monads such as WriterT, as they tend to leak space, as described in this <https://blog.infinitenegativeutility.com/2016/7/writer-monads-and-space-leaks blog post> by Getty Ritter. Instead, you should use the WriterLog strategy that implements the writer monad on a state monad. There is no downside, as using HasWriter instead of HasState directly ensures your code adheres to the writer monad interface and does not misuse the underlying state monad.
For technical reasons, this method needs an extra proxy argument. You only need it if you are defining new instances of HasReader. Otherwise, you will want to use writer. See writer for more documentation.
Writer capability An instance should fulfill the following laws. At this point these laws are not definitive, see https://github.com/haskell/mtl/issues/5.
listen @t (pure a) = pure (a, mempty)
listen @t (tell @t w) = tell @t w >> pure (w, w)
listen @t (m >>= k) = listen @t m >>= \(a, w1) -> listen @t (k a) >>= \(b, w2) -> pure (b, w1 `mappend` w2)
pass @t (tell @t w >> pure (a, f)) = tell @t (f w) >> pure a
writer @t (a, w) = tell @t w >> pure a

A note on the HasSink super class.

HasSink offers one yield method with the same signature as tell. Many people's intuition, however, wouldn't connect the two: yielding tosses the value down some black-box chute, while telling grows and accumulation via the monoid. The connection is since the chute is opaque, the tosser cannot rule out there being such an accumulation at the chutes other end. Formally, we reach the same conclusion. HasSink has no laws, indicating the user can make no assumptions beyond the signature of yield. HasWriter, with tell defined as yield, is thus always compatable regardless of whatever additional methods it provides and laws by which it abides.
Type synonym using the TypeOf type family to specify HasWriter constraints without having to specify the type associated to a tag.