具有两个参数的构造函数的适用样式解析器 [英] Applicative style parser for constructor with two arguments

查看:170
本文介绍了具有两个参数的构造函数的适用样式解析器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为尖括号中的逗号分隔的一对值编写解析器。我得到了以下方法:

  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 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.

这篇关于具有两个参数的构造函数的适用样式解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆