I was writing some Haskell earlier today. Came up with something along the lines of
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Foo a = Foo { ParsecT String () (Writer DefinitelyAMonoid) a }
deriving (Functor, Applicative, Monad, MonadWriter DefinitelyAMonoid)
This did not compile. "No instance for (MonadWriter DefinitelyAMonoid (ParsecT String () (Writer DefinitelyAMonoid)))
arising from the 'deriving' clause of a data type declaration", GHC told me. So I decided to see if some other MTL classes would work, and they did. Reader
and MonadReader
, and Writer
and MonadWriter
. So I turned was directed by a Discord user to Hackage, where the problem was clear:
MonadState s m => MonadState s (ParsecT s' u m)
MonadReader r m => MonadReader r (ParsecT s u m)
MonadError e m => MonadError e (ParsecT s u m)
No MonadWriter
instance can make it through the ParsecT
transformer! Seemed for all the world to me like a mere oversight, and I just barely realized before opening an issue on Github that this might be deliberate. So I took a look at Megaparsec:
(Stream s, MonadState st m) => MonadState st (ParsecT e s m)
(Stream s, MonadReader r m) => MonadReader r (ParsecT e s m)
(Stream s, MonadError e' m) => MonadError e' (ParsecT e s m)
Again, no MonadWriter
.
Why do neither Parsec nor Megaparsec provide a MonadWriter
instance for ParsecT
? Is there something special about parser monads like these that keep them from playing nice with writers? Is there something similar to this going on?