Search code examples
haskellparsec

Parsec: Applicatives vs Monads


I'm just starting with Parsec (having little experience in Haskell), and I'm a little confused about using monads or applicatives. The overall feel I had after reading "Real World Haskell", "Write You a Haskell" and a question here is that applicatives are preferred, but really I have no idea.

So my questions are:

  • What approach is preferred?
  • Can monads and applicatives be mixed (use them when they are more useful than the other)
  • If the last answer is yes, should I do it?

Solution

  • In general, start with whatever makes the most sense to you. Afterwards consider the following.

    It is good practice to use Applicative (or even Functor) when possible. It is in general easier for a compiler like GHC to optimize these instances since they can be simpler than Monad. I think the general community advice post-AMP has been to make as general as possible your constraints. I would recommend the use of the GHC extension ApplicativeDo since you can uniformly use do notation while only getting an Applicative constraint when that is all that is needed.

    Since the ParsecT parser type is an instance of both Applicative and Monad, you can mix and match the two. There are situations where doing this is more readable - this all depends on the situation.

    Also, consider using megaparsec. megaparsec is a more actively maintained just generally cleaner more recent fork of parsec.

    EDIT

    Two things that, rereading my answer and the comments, I really didn't do a good job of clarifying:

    • the main benefit of using Applicative is that for many types it admits much more efficient implementations (eg. (<*>) is more performant than ap).

    • If you just want to write something like (+) <$> parseNumber <*> parseNumber, there is no need to drop into ApplicativeDo - it would be just more verbose. I'd use ApplicativeDo only when you start finding yourself writing very long or nested applicative expressions.