了解 Text.ParserCombinators.ReadP.sepBy1

Understanding Text.ParserCombinators.ReadP.sepBy1

我对 sepBy1

的结果感到困惑

以下代码是 运行 在 ghci

λ> import Text.ParserCombinators.ReadP
λ> import Data.Char

λ> readP_to_S ((munch1 isAlpha) `sepBy1` (char '-')) "dish-dash-dosh"
[(["dish"],"-dash-dosh"),(["dish","dash"],"-dosh"),["dish","dash","dosh"],"")]

  1. 为什么输出不是[(["dish","dash","dosh"],"")]

以下doctest唯一一个失败的。

-- |
-- >>> readP_to_S readValues "dish-dash-dosh"
-- [(V ["dish","dash","dosh"],"")
readValues :: ReadP Value
readValues = do
  xs <- (munch isAlpha) `sepBy1` (char '-')
  pure $ V xs
Main.hs:64: failure in expression `readP_to_S readValues "dish-dash-dosh"'
expected: [(V ["dish","dash","dosh"],"")
 but got: [(V ["dish"],"-dash-dosh"),(V ["dish","dash"],"-dosh"),(V ["dish","dash","dosh"],"")]

我正在使用 ReadP 作为我数据的 Read 实例。 Read 实例的代码正在运行,但我很困惑。

没做过复杂的解析,总觉得运行ReadP会return以单元素列表[(result,"")]的形式输出,显然不是案.

data Value = V [String]
  deriving Show

-- |
-- >>> read "dish-dash-dosh" :: Value
-- V ["dish","dash","dosh"]
--
instance Read Value where
  readPrec = readP_to_Prec (const readValues)

  1. 是不是只有最后一个[(Value,String)]snd什么都没有的情况下read才会成功,这个列表中的其他元素在任何地方都没有用?

我知道有其他选择 可以做到这一点。这个问题只是关于理解 sepBy 输出及其用法。

运行 ReadP 将 return 所有可能的解析。您可以通过指定 sepBy1 解析之后应该发生的事情来限制有效解析的数量,例如输入结束或其他语法元素。

例如,尝试这样的事情:

readValues = do
  xs <- (munch isAlpha) `sepBy1` (char '-')
  eof
  pure $ V xs

附录...

ReadS 类型遵循经典 Hutton 和 Meijer 论文 Monadic Parsing in Haskell 中提出的单子解析的发展。从现有的少量文档中,我了解到 ReadP 实现了对所有备选方案的并行探索。对创建 ReadP 动作有很多支持,但对 ReadS 的支持不多,所以我认为您通过构建 ReadP 动作然后使用 [=18] 正确地使用了该库=] 最后。当我使用该模块时,我刚刚获取了 ReadS 操作的第一个匹配项(或者 returned 一个解析错误,如果它是空列表。)

ReadPrec monad 用于支持优先级,它基本上是 ReaderT Int ReadP -- 这里 Int 是当前优先级。同样,看起来您从 ReadP 解析器开始,然后使用 liftreadP_to_Prec 将其转换为 ReadPrec 操作。要 运行 你可以使用 readPrec_to_S 就像 ReadP 的情况一样。