在模块Text.ParserCombinators.ReadP
中,munch
(和munch1
)文档说:
解析满足谓词的前零个或多个字符。总是成功,一旦消耗了所有角色,因此与
(many (satisfy p))
不一样。
他们有什么不同?
答案 0 :(得分:8)
首先,让我们找一个反例,让我们使用Haskell工具自动完成。 QuickCheck库可以很快给我们这样一个反例:
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
我们要求它测试两个解析器much pred
和many (satisfy pred)
是否相同。 QuickCheck立即发现它们不同并尝试尽可能短的反例:
*** Failed! Falsifiable (after 5 tests and 2 shrinks):
[("a","")] /= [("","a"),("a","")]
所以munch pred
总是无条件地使用'a'
,而many (satisfy pred)
会给出不确定的答案 - 它可能会也可能不会消耗'a'
。
例如,考虑在字符串"abcd"
上运行以下两个解析器:
test1 = munch (> 'A') >> string "cd"
test2 = many (satisfy (> 'A')) >> string "cd"
第一个失败,因为munch
会消耗整个字符串,然后无法匹配"cd"
。第二个成功,因为many (satisfy ...)
创建所有可能的分支
[("","abcd"),("a","bcd"),("ab","cd"),("abc","d"),("abcd","")]
和string "cd"
在消耗"ab"
的分支上成功。