[Haskell-cafe] Applicative combinators from Parsec

andy morris andy at adradh.org.uk
Fri Mar 13 09:57:20 EDT 2009


2009/3/13 Martijn van Steenbergen <martijn at van.steenbergen.nl>:
> Hello,
>
> Looking at Parsec 3 I see:
>
>> chainr1 :: (Stream s m t) => ParsecT s u m a ->
>>           ParsecT s u m (a -> a -> a) -> ParsecT s u m a
>> chainr1 p op = scan where
>>  scan = do x <- p; rest x
>>  rest x = (do f <- op; y <- scan; return (f x y)) <|> return x
>>
>
> But if I remove the type signature and let GHC infer it for me, I get a much
> more generic type:
>
>> chainr1 :: (Alternative m, Monad m) => m a -> m (a -> a -> a) -> m a
>
> But we don't really need m to be a monad since we're only doing applicative
> operations, so after some rewriting we get:
>
>> chainr1 :: Alternative f => f a -> f (a -> a -> a) -> f a
>> chainr1 p op = scan where
>>  scan = flip id <$> p <*> rest
>>  rest = (flip <$> op <*> scan) <|> pure id
>
> Would it be a good idea to:
> 1) make the Parsec combinators as generic as possible and
> 2) move the really generic applicative ones to Control.Applicative?
>
> Thanks,
>
> Martijn.

This reminds me of something similar I find a bit annoying:

There are some functions like (<|>) which are defined separately in
Text.Parsec and Control.Applicative, meaning that you have to hide one
of the sets. Would it be better perhaps to just have Parsec reexport
the existing functions from Applicative, or something like that?

(Currently the functions in Parsec have the more specific type as
Martijn says, but if they're generalised then I don't really see why
they need to be duplicated.)


More information about the Haskell-Cafe mailing list