gpt4 book ai didi

haskell - 当解析器的一部分成功而其余部分失败时,为什么 Parsec 不回溯?

转载 作者:行者123 更新时间:2023-12-02 14:41:27 24 4
gpt4 key购买 nike

我有这个秒差距解析器:

a = optionMaybe $ do {try $ spaceornull *> string "hello";string "No"}                        

哪里spaceornull((:[]) <$> try space) <|> string ""

当我用输入“”测试 a 时,我得到:

Left (line 1, column 2):
unexpected end of input
expecting "hello"

我不明白这个,spaceornull *> string "hello"应该失败,因为没有“hello”,然后使用 try秒差距回溯,现在没有消耗输入,但 try无论如何都会失败,因此解析器传递给 optionMaybe ( do 中的那个)完全失败,它不应该尝试消耗更多输入,因此我们最终会得到一个失败的解析器,而不会消耗任何输入,所以我应该得到 Right Nothing

但是错误消息表明,空间已被消耗,所以 try并没有真正回溯,try当解析器的一部分成功时不回溯?以及如何使其回溯上述内容?

最佳答案

try与是否允许失败无关。它只是使得在失败的情况下可以回溯,但是要开始回溯,您需要提供一个替代解析器来从该点开始。通常的方法是使用 <|> operator :

a = optionMaybe $ (try $ spaceornull *> string "hello") <|> string "No"

OTOH,您的代码相当于

a = optionMaybe $ (try $ spaceornull *> string "hello") >> string "No"

其中单子(monad)链接 operator >> (与 *> 相同)在 Parsec 的情况下将检查 LHS 是否成功,然后继续运行 RHS 解析器。一定是这样,因为你也可以这样写:

a = optionMaybe $ do
s <- try $ spaceornull *> string "hello"
string $ "No"++s

在这里,我使用了第一个解析器的结果(您只是将其丢弃,而不是 <- -将其与任何变量匹配)来决定第二个解析器应该查找的内容。这显然只有第一个真正成功的情况下才有可能!

<小时/>

基本上,<|>仅当 LHS 在第一个字符处立即失败,或者使用 try 设置回溯点时才有效。 。这样做的原因是,如果秒差距需要在每个需要检查的替代方案之前留下回溯点,那么效率会非常低。

关于haskell - 当解析器的一部分成功而其余部分失败时,为什么 Parsec 不回溯?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39057940/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com