haskell - 具有两个参数的构造函数的应用样式解析器

标签 haskell parsec applicative

我想为尖括号中逗号分隔的一对值编写一个解析器。我通过以下方法让它工作:

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

编写这样的解析器的最佳方法是什么?理想情况下,我想重用标准秒差距解析器,例如角度,并尽可能多地使用应用程序。

最佳答案

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.

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

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

从里到外,一个 bar被解析,然后是 comma ,被丢弃,另一个 bar ,然后构造函数 Foo应用于两个已解析的bar s。最后,所有内容都包含在 angles 中。组合器,以便得到以下形式的字符串

< bar , bar >

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

将忽略其中一个结果的解析器与 *> 结合起来和<*应用组合器消除了对 pair 的需要组合器,并且可以轻松推广到采用任意数量参数的构造函数。

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

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

这比使用括号更好

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

pure ,

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

如果没有它,就需要某种形式。

关于haskell - 具有两个参数的构造函数的应用样式解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14067552/

相关文章:

haskell - Haskell 中的唯一 ID/计数器

haskell - 如何解析无序语法

parsing - 有没有更简单的方法来为 8 位十进制整数编写这个 Haskell Parsec 解析器?

c - 使用 Stack 构建时如何包含从 haskell 源文件生成的 'xxx_stub.h' 文件

haskell - 计算大文件中的字符时内存不足

haskell - 使用 haskell 删除 stdin 中的项目

haskell - 使用 Text.Combinators.Parsec 进行不区分大小写解析的最简洁方法是什么?

java - CompletableFuture 是一个 Monad。但应用性在哪里呢?

Haskell:如何创建一个不允许、一个或两个 Applicative 的函数?

scala - 如何将[Future [A],Future [B]]转换为Future [Either [A,B]]