Haskell Parsec解析器:在某些条件下不会计算自定义失败

Haskell Parsec解析器:在某些条件下不会计算自定义失败,haskell,parsec,Haskell,Parsec,我刚刚开始学习使用Parsec解析字符串,我面临着以下问题,我无法完全理解: 下面的代码包含三次解析器运行,其中两次显然会失败。奇怪的是,我的自定义失败消息只会在第二次运行时出现,而不会在第三次运行时出现 import Text.Parsec import Text.Parsec.String ps :: Parser String ps = (string "123") <|> (string "456") <|> fail "my-failure" main =

我刚刚开始学习使用Parsec解析字符串,我面临着以下问题,我无法完全理解:

下面的代码包含三次解析器运行,其中两次显然会失败。奇怪的是,我的自定义失败消息只会在第二次运行时出现,而不会在第三次运行时出现

import Text.Parsec
import Text.Parsec.String

ps :: Parser String
ps = (string "123") <|> (string "456") <|> fail "my-failure"

main = do
     putStrLn $ "A: " ++ show (parse ps "" "123")
     putStrLn $ "\nB: " ++ show (parse ps "" "789")
     putStrLn $ "\nC: " ++ show (parse ps "" "45x")
当第二个部件的剩余部分出现故障时,有什么正确的方法使我的故障消息始终出现?我可以覆盖以前发生的任何错误吗

只有当解析器不使用任何输入时,Parsec中的组合符才会尝试下一个选项。在您的例子中,解析器字符串456匹配45x的开头,因此不再尝试其他替代方法。如果需要任意前瞻,则需要使用该函数

ps :: Parser String
ps = string "123" <|> try (string "456") <|> fail "my-failure"
来自Parsec的以下文档:

这个组合器实现选择。解析器pq首先应用p。如果成功,则返回p的值。如果p失败而不使用任何输入,则尝试解析器q。此组合符定义为等于MonadPlus类的mplus成员和Alternative的成员

该解析器称为预测解析器,因为只有当解析器p 未消耗任何输入,即前瞻性为1。这 非回溯行为允许高效的实现 语法分析器组合器和良好错误消息的生成

您可能更喜欢使用as-in-syntax元素,而不是fail-my-failure,这将生成错误消息expecting-syntax元素而不是my-failure。但您仍然需要使用try。
ps :: Parser String
ps = string "123" <|> try (string "456") <|> fail "my-failure"