很多和很多之间的差异(满足p)?

时间:2014-10-15 09:56:15

标签: parsing haskell

在模块Text.ParserCombinators.ReadP中,munch(和munch1)文档说:

  

解析满足谓词的前零个或多个字符。总是成功,一旦消耗了所有角色,因此与(many (satisfy p))不一样。

他们有什么不同?

1 个答案:

答案 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 predmany (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"的分支上成功。