5

有人建议我使用 attoparsec 来解析文件,现在我必须了解如何使用它;有人给了我这段代码:

#

type Environment = M.Map String String 
import Data.Attoparsec (maybeResult)
import qualified Data.Attoparsec.Char8 as A
import qualified Data.ByteString.Char8 as B
environment :: A.Parser Environment
environment = M.fromList <$> A.sepBy entry A.endOfLine
parseEnvironment = maybeResult .flip A.feed B.empty . A.parse environment
spaces = A.many $ A.char ' '
entry = (,) <$> upTo ':' <*> upTo ';'
upTo delimiter = B.unpack <$> A.takeWhile (A.notInClass $ delimiter : " ")
                      <* (spaces >> A.char delimiter >> spaces)

效果很好,但我不知道为什么:使用翻转的原因是什么,将A.feed的参数放在不同的顺序中不是更容易吗?为什么有B.empty?有一些我可以学习的教程吗?提前致谢

4

1 回答 1

6

在这个 StackOverflow questionfeed的答案中有对需要的解释。正如 Bryan O'Sullivan(Attoparsec 的创造者)所说:

如果您编写的 attoparsec 解析器在失败之前消耗尽可能多的输入,那么当您到达输入的末尾时,您必须告诉部分结果继续。

你可以通过给它一个空的字节串来做到这一点。

我承认我写了有问题的代码,实际上我并没有pointfree在这种情况下使用。简单的组合在这里对我来说很有意义:您运行A.parse environment解析器(在我看来,这感觉比尖锐的版本更干净:flip A.feed B.emptyMaybemaybeResult

parseEnvironment b = maybeResult $ A.feed (A.parse environment b) B.empty

其余的是我认为相当惯用的应用解析,尽管我不确定为什么我会使用>>而不是*>.

于 2010-08-27T16:33:28.257 回答