What is the best way to write such a parser? Ideally, I would like to use standard Parsec parsers at such angles and make the most of the applicative capabilities.
In an applicative style, your parser will
foo = angles $ Foo <$> bar <* comma <*> bar
Coming from the inside, a bar parsed, then comma discarded, and another bar discarded, then the Foo constructor is applied to two parses of bar s. Finally, everything is wrapped in an angles combinator, so the form string
< bar , bar >
parsed ( bar should probably consume trailing spaces).
The combination of parsers that ignore the result of one with the applicative combinators *> and <* eliminates the need for a pair combinator and easily generalizes constructors that take an arbitrary number of arguments.
Like CA McCann mentioned in the comment, the combinator (<$) (which is part of the Functor GHC implementation with the default implementation (<$) = fmap . const , but it is not part of the standard language) is also useful if you want to ignore the leading token. Using this, you can write
Foo <$ ignoreMe <*> bar <* comma <*> baz
which is better than using parentheses
Foo <$> (ignoreMe *> bar) <* comma <*> baz
or pure
pure Foo <* ignoreMe <*> bar <* comma <*> baz
as it would be necessary in some form without him.
source share