我必须解析一些文件并将它们转换为一些预定义的数据类型。
Haskell 似乎为此提供了两个软件包:
它们两者有什么区别,哪一个更适合根据某些规则解析文本文件?
Parsec 适用于“面向用户”的解析器:输入量有限但错误消息很重要的事情。它不是非常快,但如果你的输入很小,这应该没关系。例如,对于几乎所有编程语言工具,我都会选择 Parsec,因为——从绝对意义上说——即使是最大的源文件也没有那么大,但错误消息确实很重要。
Parsec 可以处理不同的输入类型,这意味着您可以将它与标准String
或来自某种外部词法分析器的令牌流一起使用。由于它可以使用String
,它可以很好地为您处理 Unicode;内置的基本解析器喜欢digit
并且letter
支持 Unicode。
Parsec 还带有一个 monad 转换器,这意味着您可以将它分层放在一个 monad 堆栈中。例如,如果您想在解析期间跟踪其他状态,这可能很有用。您还可以寻求更多的幻觉效果,例如非确定性解析或其他东西 - monad 转换器的常见魔力。
Attoparsec 比 Parsec 快得多。当您期望获得大量输入或性能非常重要时,您应该使用它。它非常适合网络代码(解析数据包结构)、解析大量原始数据或使用二进制文件格式。
Attoparsec 可以与ByteString
s 一起工作,它是二进制数据。这使其成为实现二进制文件格式等内容的不错选择。但是,由于这是针对二进制数据的,它不处理文本编码之类的事情;为此,您应该使用 attoparsec 模块Text
。
Attoparsec 支持增量解析,而 Parsec 不支持。这对于某些应用程序(例如网络代码)非常重要,但对于其他应用程序则无关紧要。
Attorparsec 的错误消息比 Parsec 更糟糕,并且为了性能牺牲了一些高级特性。它专门用于Text
or ByteString
,因此您不能将它与来自自定义词法分析器的标记一起使用。它也不是一个单子变压器。
最终,Parsec 和 Attoparsec 迎合了非常不同的利基市场。高级别的区别是性能:如果需要,请选择 Attoparsec;如果您不这样做,请使用 Parsec。
我通常的启发式方法是选择 Parsec 作为编程语言、配置文件格式和用户输入,以及几乎所有我会用正则表达式做的事情。这些东西通常是手工制作的,所以解析器不需要扩展,但它们确实需要很好地报告错误。
另一方面,我会选择 Attoparsec 来实现网络协议、处理二进制数据和文件格式或读取大量自动生成的数据。处理时间限制或大量数据的事情,通常不是由人类直接编写的。
如您所见,选择实际上通常非常简单:用例不会重叠太多。很有可能,对于任何给定的应用程序使用哪一个将是非常清楚的。