
2009/3/13 Martijn van Steenbergen
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.)