我对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"],"")]
[(["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
会以单元素列表[(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)
read
的{{1}}中没有任何东西的情况下snd
才会成功,此列表中的其他元素在任何地方都没有使用?我知道可以选择way来做到这一点。这个问题仅仅是关于了解[(Value,String)]
的输出及其用法。
答案 0 :(得分:3)
运行ReadP
将返回所有可能的解析。您可以通过指定sepBy1
解析后应进行的操作来限制有效解析的次数,例如输入结束或其他语法元素。
例如,尝试类似的操作:
readValues = do
xs <- (munch isAlpha) `sepBy1` (char '-')
eof
pure $ V xs
附录...
ReadS
类型遵循经典的Hutton and Meijer论文[dcl.ref]/1中介绍的单子语法解析方法。从很少的文档中,我了解到ReadP
实现了所有替代方案的并行探索。创建ReadP
操作有很多支持,而对于ReadS
却没有太多支持,因此我认为您通过构建ReadP
操作然后使用{{1 }} 在末尾。使用模块后,我刚进行了readP_to_S
操作的第一个匹配项(或者如果是空列表,则返回解析错误)。
ReadS
monad用于支持优先级,它基本上是ReadPrec
,这里的ReaderT Int ReadP
是当前优先级。同样,您似乎从Int
解析器开始,然后使用ReadP
或ReadPrec
将其转换为lift
操作。要运行它,您可以像使用readP_to_Prec
一样使用readPrec_to_S
。