MonadWriter instance for Either w?

In trying to understand the MonadWriter class, I have been writing instance for different Monads, and then got stuck on Either. I don’t see how to write listen or pass for the Left constructor, as there is no way to create a value of type a for the Left constructor for listen and pass.

Is this instance possible?

instance (Monoid w) => MonadWriter w (Either w) where
    tell :: w -> Either w ()
    tell = Left

    writer :: (a, w) -> Either w a
    writer (a, _) = Right a

    listen :: Either w a -> Either w (a, w)
    listen (Right a) = Right (a, mempty)
    listen (Left w) = ?

    pass :: Either w (a, w -> w) -> Either w a
    pass (Right (a, _)) = Right a
    pass (Left _) = ?

You have a bigger problem than implementing listen and pass. tell and writer should satisfy the following relationship:

writer (a, w) = tell w *> pure a

But with your implementations, this is:

writer (a, w) = tell w *> pure a
Right a       = Left w *> Right a
              = Left w

Either is not naturally a MonadWriter. You could write an instance that type-checks but it won’t satisfy the expectations that come with the class. MonadWriters are intuitively product-like, not sum-like.

4 Likes