
On Sun, 3 Feb 2008, Antoine Latter wrote:
Another picky nit:
The monad transformer type is defined as such:
data ParsecT s u m a = ParsecT { runParsecT :: State s u -> m (Consumed (m (Reply s u a))) }
with the Consumed and reply types as:
data Consumed a = Consumed a | Empty !a
data Reply s u a = Ok !a !(State s u) ParseError | Error ParseError
What's the advantage of having a double-wrapping of the base monad `m' over the simpler type:
data ParsecT s u m a = ParsecT { runParsecT :: State s u -> m (Consumed (Reply s u a)) }
It's a necessary part of how Parsec works - both the Consumed and the Reply depend on the input stream, which is now generated from within the base monad. The Consumed result is evaluated in advance of the Reply, so keeping the computations separate preserves an important piece of laziness as m could be a strict monad. For now it's probably a good idea to look for issues that're visible to client code? Turning Parsec into a transformer was long considered an invitation to serious confusion, so it's not surprising that a few things look odd and a few others can be generalised in ways that aren't immediately obvious. -- flippa@flippac.org "The reason for this is simple yet profound. Equations of the form x = x are completely useless. All interesting equations are of the form x = y." -- John C. Baez