2

我想为尖括号中的逗号分隔值对编写解析器。我让它使用以下方法:

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)

但是我更喜欢 Foo 构造函数采用两个参数而不是一个元组:

data Foo = Foo Bar Bar

编写这样的解析器的最佳方法是什么?理想情况下,我想重用标准 Parsec 解析器,angles并尽可能多地使用 applicative。

4

1 回答 1

8

编写这样的解析器的最佳方法是什么?理想情况下,我想重用标准 Parsec 解析器这样的角度并尽可能多地使用 applicative。

在应用风格中,您的解析器将是

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

由内而外, abar被解析,然后 acomma被丢弃,另一个bar, 然后构造函数Foo应用于两个解析bar的 s。最后将所有的东西都包裹到angles组合器中,这样就形成了一个字符串的形式

< bar , bar >

被解析(bar应该可能消耗尾随空格)。

将忽略一个结果的解析器*><*应用组合器相结合,消除了对组合器的需要,pair并且很容易推广到采用任意数量参数的构造函数。

正如CA McCann在评论中提到的,如果您想忽略前导标记,(<$)组合子(它是 GHC 的Functor类实现的一部分,具有默认实现;但它不是语言标准的一部分)也很有用。(<$) = fmap . const使用它,您可以编写

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

这比使用括号更好

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

pure,

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

就像没有它的某种形式所需要的那样。

于 2012-12-28T10:55:04.407 回答