在模块中Text.ParserCombinators.ReadP,munch(和munch1)文档说:
解析满足谓词的第一个零个或多个字符.总是成功,一次消耗了所有的角色因此不一样
(many (satisfy p)).
他们有什么不同?
首先,让我们找一个反例,让我们使用Haskell工具自动完成.该快速检查库可以非常迅速地给我们这样一个反例:
import Data.Function (on)
import Text.ParserCombinators.ReadP
import Test.QuickCheck
prop_ParseTest :: String -> Property
prop_ParseTest input = on (===) runParser (munch pred) (many (satisfy pred))
where
runParser :: ReadP a -> [(a, String)]
runParser = flip readP_to_S input -- run a given parser on a given input
pred :: Char -> Bool
pred = (> 'A')
main :: IO ()
main = quickCheck prop_ParseTest
Run Code Online (Sandbox Code Playgroud)
我们要求它来测试,是否两个解析器much pred和many (satisfy pred)是相同的.QuickCheck立即发现它们不同并尝试尽可能短的反例:
*** Failed! Falsifiable (after 5 tests and 2 shrinks):
[("a","")] /= [("","a"),("a","")]
Run Code Online (Sandbox Code Playgroud)
所以munch pred总是'a'无条件地消费,同时many (satisfy pred)给出一个不确定的答案 - 它可能会也可能不会消耗'a'.
例如,考虑在字符串上运行以下两个解析器"abcd":
test1 = munch (> 'A') >> string "cd"
test2 = many (satisfy (> 'A')) >> string "cd"
Run Code Online (Sandbox Code Playgroud)
第一个失败,因为munch消耗整个字符串然后它不可能匹配"cd".第二个成功,因为many (satisfy ...)创建了所有可能的分支
[("","abcd"),("a","bcd"),("ab","cd"),("abc","d"),("abcd","")]
Run Code Online (Sandbox Code Playgroud)
并string "cd"在消费的分支上取得成功"ab".