我正在阅读箭头教程。 https://en.wikibooks.org/wiki/Haskell/Understanding_arrows#Avoiding_leaks。 读这部分我很困惑
solfege :: Parser Char String
solfege = string "Do" <|> string "Re" <|> string "Mi"
通过最后一个例子,我们可以表明 Swierstra 和 Duponcheel 试图解决哪个问题。当对字符串“Fa”运行视唱练习时,我们无法检测到解析器将失败,直到所有三个替代方案都失败。如果我们有更复杂的解析器,其中一种替代方案只有在尝试消耗大量输入流后才可能失败,那么我们将不得不以同样的方式沿着解析器链向下移动。后面的解析器可能使用的所有输入都必须保留在内存中,以防其中一个解析器恰好能够使用它。这可能会导致比您天真的预期更多的空间使用量 - 这种情况通常称为空间泄漏。
我不明白
solfege
有造成空间泄漏的风险。 solfege
(string "Do"
、string "Re"
和string "Mi"
)中的每个替代方案都无法与“Fa”的第一个字符“F”进行比较。如果这些替代方案消耗多个字符并失败,那么我可以接受 solfege
会导致空间泄漏。然而,只有当 string
的实现很愚蠢时,这才有可能。另外,我很难想象一个单子解析器会在消耗不必要的令牌后失败,除非它故意写得不好。
我在文章中遗漏了什么吗?
您可能忽略的关键部分是这一点:
如果我们有更复杂的解析器,其中一种替代方案只有在尝试消耗大量输入流后才可能失败,...
因此,
string "Do"
并不意味着按字面意思理解,而是代表一个解析器,该解析器执行更多工作,并且可能必须在输入中任意向前查看才能知道它是否应该失败。