避免在 Parsers 库的解析器中使用 fail

Avoiding usage of fail in parsers from Parsers library

据我所知,不推荐使用 fail,稍后将被删除。

在下面的Parsers/Trifecta例子中应该正确使用什么而不是失败?

parserNaturalNoLeadZero :: Parser Integer
parserNaturalNoLeadZero = do
  digits <- some digit
  if length digits > 1 && head digits == '0'
    then fail "Leading Zeros"
    else return $ read digits

如文档所述,正在引入新的 MonadFail class 来履行该职责。

但是,对于像解析器这样的东西,明智的选择通常是 empty,它已经存在了很长时间。

秒差距:

三连胜:

唯一的区别是它们产生的错误信息。

  • 对意外标记使用 unexpectedunexpected "token" 将导致类似 "unexpected: 'token'".

  • 的错误消息
  • 用 high-level 结构注释解析器,它们使用 (<?>).

    This is normally used at the end of a set alternatives where we want to return an error message in terms of a higher level construct rather than returning all possible characters.

    parseExpr = ... <?> "expression"
    parseId = ... <?> "identifier"
    parseTy = ... <?> "type"
    
  • empty 不会产生任何错误消息。回溯并让另一个分支成功或负责报告有意义的错误仍然有用。

  • 对其他类型的错误使用 fail,图书馆不能对其中的内容做出太多假设,因此他们可能会将其参数视为原始消息。