在Haskell中,attoparsec或parsec是什么?

80

我需要解析一些文件并将它们转换为预定义的数据类型。

Haskell 提供了两个用于这个任务的包:

  1. attoparsec
  2. parsec

这两个包有什么区别?哪一个更适合根据某些规则解析文本文件?


它们大致相等。attoparsec更快,但parsec可能已默认安装,因此更方便。 - sanityinc
1
模块Data.Attoparsec.ByteString的文档中有Parsec和Attoparsec之间的比较:http://hackage.haskell.org/package/attoparsec-0.10.4.0/docs/Data-Attoparsec-ByteString.html - danidiaz
6
我想提一下,Haskell 提供了不止两个用于解析的包,你漏掉了几个非常好的,特别是 uu-parsinglibpolyparse - John L
1
现在还有parsec-fork megaparsec:https://mail.haskell.org/pipermail/haskell-cafe/2015-September/121530.html - unhammer
1个回答

149

Parsec

Parsec适用于“面向用户”的解析器: 输入量有限但错误消息很重要的情况。它并不是特别快,但如果输入较小,则速度不会成问题。例如,我会选择Parsec用于几乎所有的编程语言工具,因为即使最大的源文件在绝对意义上也不是非常大,但错误消息确实很重要。

Parsec可以处理不同类型的输入,这意味着您可以将其与标准的String或来自某种外部词法分析器的标记流一起使用。由于它可以使用String,因此它可以完美地为您处理Unicode; 像digitletter之类的内置基本解析器已经支持Unicode。

Parsec还带有一个Monad Transformer,这意味着您可以将其层叠在一个Monad堆栈中。例如,如果您想在解析过程中跟踪附加状态,则可能会很有用。您还可以尝试更多的效果,如非确定性解析等 - Monad Transformers的惯常魔力。

Attoparsec

Attoparsec比Parsec快得多。当您需要处理大量输入或性能真正重要时,应该使用它。它非常适用于像网络代码(解析数据包结构)、解析大量原始数据或处理二进制文件格式等方面。

Attoparsec可以处理ByteString,这是一种二进制数据。这使得它成为实现二进制文件格式之类的东西的好选择。然而,由于这是针对二进制数据的,因此它不会处理文本编码; 对此,您应该使用Text的attoparsec模块。

Attoparsec支持增量解析,而Parsec不支持。这对于某些应用程序(例如网络代码)非常重要,但对于其他应用程序则无关紧要。

Attorparsec的错误信息比Parsec更糟糕,并且为了提高性能而牺牲了一些高级特性。它专门针对

哪一个好?

最终,Parsec和Attoparsec适用于非常不同的领域。高层次的区别在于性能:如果需要,则选择Attoparsec;如果不需要,则选择Parsec。

我的通常启发式规则是:选择Parsec进行编程语言、配置文件格式和用户输入以及几乎任何我原本会使用正则表达式处理的内容。这些通常是手工制作的东西,因此解析器不需要扩展,但需要报告错误信息。

另一方面,我会选择Attoparsec来实现网络协议、处理二进制数据和文件格式或读取大量自动生成的数据。处理时间约束或大量数据的情况下,通常不是由人直接编写的。

如您所见,选择其实常常很简单:使用情况并不重叠。很可能,在任何给定的应用程序中,将很清楚应该使用哪一个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接