我想在尖括号中为逗号分隔的值对编写解析器。我让它使用以下方法:
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。
答案 0 :(得分:8)
编写这样一个解析器的最佳方法是什么?理想情况下,我想重用标准Parsec解析器这样的角度,并尽可能使用applicative。
在应用程序样式中,您的解析器将是
foo = angles $ Foo <$> bar <* comma <*> bar
自上而下,解析bar
,然后丢弃comma
,另一个bar
,然后将构造函数Foo
应用于解析后的两个bar
angles
秒。最后,所有内容都包含在< bar , bar >
组合子中,以便形成
bar
解析(*>
应该使用尾随空格。)
将解析器的结果与<*
和pair
应用组合器相结合,解析器消除了对(<$)
组合子的需要,并且很容易推广给构造函数采用任意数量的参数。
作为评论中提及的C.A. McCann,Functor
组合子(GHC实施(<$) = fmap . const
类的一部分,默认实现Foo <$ ignoreMe <*> bar <* comma <*> baz
;但它不是如果你想忽略一个领先的标记,那么语言标准的一部分也很有用。使用它,你可以写
Foo <$> (ignoreMe *> bar) <* comma <*> baz
比使用括号
更好pure
或pure Foo <* ignoreMe <*> bar <* comma <*> baz
,
{{1}}如果没有它,将以某种形式要求。