【问题标题】:Chain two parsers in Haskell (Parsec)在 Haskell (Parsec) 中链接两个解析器
【发布时间】:2020-09-07 15:13:36
【问题描述】:

Parsec 提供了一个运算符来在两个解析器之间进行选择:

(<|>)
  :: Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a
     -> Text.Parsec.Prim.ParsecT s u m a

是否有类似的函数来链接两个解析器?我使用 Hoogle 没有找到具有相同签名的人。


举个例子,假设我想解析任意后跟一个数字的单词。我的第一个想法是使用&gt;&gt;,但它似乎不起作用。

parser = many1 letter >> optional (fmap pure digit)

我使用fmap pure 将数字转换为实际字符串,从而匹配many1 letter 的解析类型。不知道有没有用。

【问题讨论】:

  • &gt;&gt;*&gt; do 序列解析器,通过它们的 Monad/Applicative 实例,但它们只返回第二个解析器的结果。 (同样,&lt;* 返回第一个的结果;并且为方便起见,x &lt;$ p 返回一个常量值x,相当于常见的模式p *&gt; pure x)。您并不严格需要那里的fmap pure,因为结果类型不需要匹配,但使用&lt;$&gt;&lt;*&gt; 组合结果通常可能更方便(如在@SergeyKuz1001 的回答中)如果类型相同。
  • 解释的很清楚,谢谢!

标签: parsing haskell parsec


【解决方案1】:

试试这个:

parser = (++) <$> many1 letter <*> option "" (fmap pure digit)

这相当于:

parser = pure (++) <*> many1 letter <*> option "" (fmap pure digit)

option [] (fmap pure digit) 如果解析器 digit 失败,则返回空字符串,否则返回一个数字字符的字符串。

您还可以使用 do-notation 来获得更易读的代码:

parser = do
    s1 <- many1 letter
    s2 <- option "" (fmap pure digit)
    return (s1 ++ s2)

【讨论】:

  • 我猜option "" 会更清楚一点,但无论如何这是一个很好的答案,谢谢!
猜你喜欢
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-06
  • 1970-01-01
  • 2016-06-19
相关资源
最近更新 更多