I recently started learning to use Parsec to write parsers. I am wondering if the following is true:
Even though <*
is implemented as (<*) = liftA2 const
, when used with parsec, is it the same as:
p1 <* p2 = do { r1 <- p1; _ <- p2; return r1 }
And it seems that when using parsec the operator *>
and >>
are exactly the same since they both throw away the result of the first parser?
Generally, when a type has instances of both Applicative
and Monad
, it is considered polite for those instances to agree in the way you suggest, at least semantically. In some instances the Applicative
version may be more efficient (in some cases even asymptotically so!), though for parsec at least this is not the case; from the source:
instance Applicative.Applicative (ParsecT s u m) where
pure = return
(<*>) = ap -- TODO: Can this be optimized?