具有两个参数的构造函数的适用样式解析器 [英] Applicative style parser for constructor with two arguments
问题描述
我想为尖括号中的逗号分隔的一对值编写解析器。我得到了以下方法:
pair p1 p2 = do
x1 < - p1
逗号
x2 < - p2
返回(x1,x2)
数据Foo = Foo(Bar,Bar)
foo :: Parser Foo
foo = Foo< $> (angle $ pair bar bar)
然而我更喜欢Foo构造函数来取两个参数而不是元组:
data Foo = Foo Bar Bar
编写这样一个解析器的最好方法是什么?理想情况下,我想重复使用标准的Parsec解析器,例如 angles
,并尽可能使用applicative。
写这样一个解析器的最好方法是什么?理想情况下,我想重复使用标准的Parsec解析器,并尽可能多地使用应用。
在应用样式中,解析器会be
foo =角度$ Foo< $> bar< *逗号*> bar
从头开始, bar
是然后是一个逗号
,这会被丢弃,另一个 bar
,那么构造函数 Foo
应用于两个已解析的栏
s。最后,将所有元素都包装到角度
组合器中,以便形成一个字符串
<酒吧,酒吧>
被解析( bar
$ b 结合解析器忽略 *>
和的结果, < *
应用组合器消除了对 pair
组合子的需要,并且可以轻松地将其推广到构造函数接受任意数量的参数。
由于 CA McCann 在评论中提到(< $)
组合子(它是GHC的 Functor
class,默认实现(< $)= fmap。const
;但它不是语言标准的一部分)也很有用,如果你想忽略领先的令牌。使用它,你可以写成:
Foo< $ ignoreMe< *> bar< *逗号*> baz
比使用圆括号更好
Foo< $> (ignoreMe *>栏)< *逗号> baz
或纯
,
纯Foo< * ignoreMe< *> bar< *逗号*> baz
如果没有它,某些形式需要。
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.
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 bar
s. 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.
这篇关于具有两个参数的构造函数的适用样式解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!