Applicative style parser for constructor with two arguments

拟墨画扇 提交于 2019-12-24 00:15:04

问题


I want to write a parser for a comma separated pair of values in angle brackets. I got it to work with the following approach:

pair p1 p2 = do
    x1 <- p1
    comma
    x2 <- p2
    return (x1, x2)

data Foo = Foo (Bar, Bar)

foo :: Parser Foo
foo = Foo <$> (angles $ pair bar bar)

However I would prefer the Foo constructor to take two parameter rather than a tuple:

data Foo = Foo Bar Bar

What is the best way to write such a parser? Ideally I would like to reuse standard Parsec parsers such a angles and use applicative as much as possible.


回答1:


What is the best way to write such a parser? Ideally I would like to reuse standard Parsec parsers such a angles and use applicative as much as possible.

In applicative style, your parser would be

foo = angles $ Foo <$> bar <* comma <*> bar

Going inside out, a bar is parsed, then a comma, which is discarded, and another bar, then the constructor Foo is applied to the two parsed bars. Finally, all is wrapped into the angles combinator, so that a string of the form

< bar , bar >

is parsed (bar should probably consume trailing whitespace).

Combining parsers ignoring the result of one with the *> and <* applicative combinators eliminates the need for the pair combinator and easily generalises to constructors taking an arbitrary number of arguments.

As C.A. McCann mentioned in a comment, the (<$) combinator (which is part of GHC's implementation of the Functor class, with the default implementation (<$) = fmap . const; but it's not part of the language standard) is useful too, if you want to ignore a leading token. Using that, you can write

Foo <$ ignoreMe <*> bar <* comma <*> baz

which is nicer than using parentheses

Foo <$> (ignoreMe *> bar) <* comma <*> baz

or pure,

pure Foo <* ignoreMe <*> bar <* comma <*> baz

as would be required in some form without it.



来源:https://stackoverflow.com/questions/14067552/applicative-style-parser-for-constructor-with-two-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!