【问题标题】:Creating a parser combinator of type Parser a -> Parser b -> Parser (Either a b)创建 Parser a -> Parser b -> Parser 类型的解析器组合器(a b)
【发布时间】:2013-11-24 19:44:37
【问题描述】:

我想解析一些文本,其中某些字段大部分时间都有结构,但偶尔(由于特殊的大小写、拼写错误等)这种结构会丢失。

例如常规大小写为Cost: 5,但偶尔会显示为Cost: 5mCost: 3 + 1 per ally,或其他一些随机的东西。

在普通解析器 (p) 不工作的情况下,我想退回到只将整行作为字符串的解析器。

为此,我想创建一个Parser a -> Parser b -> Either a b 类型的组合器。但是,如果不执行case parse p "" txt of ... 之类的操作,我无法弄清楚如何检查尝试查看第一个解析器是否成功的结果。

我看不到组合器中的构建,但我确信有一些简单的方法可以解决我缺少的问题

【问题讨论】:

    标签: parsing haskell parsec


    【解决方案1】:

    我想你想要这样的东西

    eitherParse :: Parser a -> Parser b -> Parser (Either a b)
    eitherParse a b = fmap Left (try a) <|> fmap Right b
    

    try 只是为了确保如果a 消耗一些输入然后失败,您将正确回溯。然后你可以使用正常的方法来运行解析器来产生Either ParseError (Either a b)

    这很容易转换成你的Either a b

    case parse p "" str of
      Right  (Left a) -> useA a
      Right (Right b) -> useB b
      Left   err      -> handleParserError err
    

    【讨论】:

    • 忽略此评论——我在发布后不久就想到了这一点,但 GHC 无法简单地统一 (fmap Left foo) :: Either a b, (fmap Right bar):: 中的 a 和 b要么是 b
    • @MrBones 你能澄清一下你的意思吗?这对我来说编译得很好
    • 我错了,我在交换参数a和b时没有更正类型签名。
    【解决方案2】:

    试试这个:(<|>) :: ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a

    通常你可以这样使用它:

    try p <|> q
    

    【讨论】:

    • 他们希望组合器支持不同的类型。
    猜你喜欢
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 2012-03-18
    • 2017-12-28
    • 1970-01-01
    • 2011-04-21
    相关资源
    最近更新 更多