
Martijn van Steenbergen wrote:
Ben Franksen wrote:
I was refering to the 1996 paper titled "Deterministic, Error-Correcting Combinator Parsers", where the 'fail' parser needs extra arguments. Maybe I am dense, but I can't see how to avoid the arguments w/o constraining the type of the result (which would mean the parsers can't even be instances of Applicative).
The trick is to not constrain the result type: pFail should be polymorphic in its result type. Suppose you use the list of successes parser:
type Parser s a = [s] -> [(a, [s])]
Then pFail may be defined as:
pFail :: Parser s a pFail = const []
i.e. polymorphic in output (and input too), because [] :: [a] is polymorphic in its element type.
I never claimed that _no_ parser combinator library can offer pFail :: p a ; indeed, most do. The problem I see is when parsers are supposed to be error-correcting, particularly if this means they should never fail to produce a result. (A parser of the 'list of successes' type can not have this property, because [] means 'no result'.) And now the question is how some pFail :: p a can conjure up a result value if the result type a is not constrained (e.g. to have a 'default' element). The other problem is good error messages. For instance, although Parsec has a parserZero :: (Monad m) => ParsecT s u m a it is defined thus (in version 3.0.0): parserZero = ParsecT $ \s -> return $ Empty $ return $ Error (unknownError s) that is, you'll get no usable error message. Fortunately, for practical use there is parserFail :: (Monad m) => String -> ParsecT s u m a and this requires an extra argument. Cheers Ben