简体   繁体   English

如何使用parsec进行条件monadic解析?

[英]How can I do conditional monadic parsing using parsec?

Imagine the following example 想象一下下面的例子

data A = ...
data B = ...
data C = ...

convertA :: A -> C

parseA :: Parser A
parseB :: Parser B

parseC :: Parser C
parseC = do
  a <- parseA
  if parsed? a
    then return $ convertA a
    else parseB

Is there a way to implement such logic where I can try to use a parser, and if it is successful do some transformation on the result, and otherwise use another parser? 有没有办法实现这样的逻辑,我可以尝试使用解析器,如果成功,对结果进行一些转换,否则使用另一个解析器? I know this particular example could be written such as the following 我知道这个特殊的例子可以写成如下

parseC = (convertA <$> parseA) <|> parseB

but is there a more general way to represent this pattern in the monadic notation? 但是有一种更通用的方式来表示这种模式的monadic符号吗?

You can represent it more monadically, but I don't know if I'd call it a more general pattern. 你可以用monadically代表它,但我不知道我是否称它为更通用的模式。

Normally, success or failure of a parser is handled implicitly through the MonadPlus and Alternative interfaces. 通常,解析器的成功或失败是通过MonadPlusAlternative接口隐式处理的。 However, you can reify success/failure and operate on it in the Monad context if you really want to. 但是,如果您真的想要,可以在Monad上下文中重新确定成功/失败并对其进行操作。 The function to do that reification is optionMaybe in Text.Parsec.Combinator . 执行该具体化的功能是optionMaybe中的optionMaybe

parseC :: Parser C
parseC = do
    ma <- optionMaybe parseA
    case ma of
        Just a -> return $ convertA a
        Nothing -> parseB

One important note here is that optionMaybe is.. special. 这里一个重要的注意事项是optionMaybe是......特别的。 It only succeeds with a Nothing result in the case when the parser provided to it fails without consuming input . 它只是一个成功的Nothing结果的情况下提供的解析器失败不消耗输入 Of course your example code is broken anyway if parseA can consume input while failing, so I assume you're familiar with that issue. 当然如果parseA在失败时消耗输入,那么你的示例代码就会被破坏,所以我假设你熟悉这个问题。 This brokenness is why I hate parsec and will never use it in my own code, by the way. 这种破坏是我讨厌parsec并且永远不会在我自己的代码中使用它的原因。 Sorry for the editorializing, I just don't think that issue is something every user should be forced to stumble over. 对于编辑抱歉,我只是不认为这个问题是每个用户都应该被迫绊倒的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM