pki*_*sky 0 haskell quickcheck
我希望下面的代码生成一个大小为1,2或3的列表生成器,每个元素都是独立生成的.
shortlist :: Arbitrary a => Gen [a]
shortlist = oneof $ map promote [[arbitrary],
[arbitrary, arbitrary],
[arbitrary, arbitrary, arbitrary]]
Run Code Online (Sandbox Code Playgroud)
REPL:
sample (shortlist :: Gen [Char])
"\255\255\255"
"ii"
"FF"
"\236\236"
"FF"
"'''"
"8"
"HH"
"\160"
"\DEL\DEL\DEL"
"\246\246"
Run Code Online (Sandbox Code Playgroud)
每个列表包含相同char的1,2或3个实例.为什么武断不按预期行事?
我真的不得不寻找promote.模块描述表明该模块中提供的功能将重用随机数种子.而不是使用promote,你应该使用像replicateM或sequence.
例如:
shortlist :: Arbitrary a => Gen [a]
shortlist = oneof $ map sequence [[arbitrary],
[arbitrary, arbitrary],
[arbitrary, arbitrary, arbitrary]]
Run Code Online (Sandbox Code Playgroud)
要么
shortlist :: Arbitrary a => Gen [a]
shortlist = oneof $ [ replicateM n arbitrary | n <- [1..3] ]
Run Code Online (Sandbox Code Playgroud)
会产生类似的东西:
> sample (shortlist :: Gen [Char])
"\SI"
"aP"
"\153\US\STX"
"#k"
"U"
"}\DC1"
"i"
"\186F"
"\148k"
"\RS|\159"
"\192L"
Run Code Online (Sandbox Code Playgroud)
在QuickCheck-2.7.6中.promote已被移至Test.QuickCheck.Gen.Unsafe模块.
那里的评论解释了你所看到的:
Gen在道德上只是一个monad:两个应该相等的生成器将给出相同的概率分布,但它们可能与随机数种子到值的函数不同.QuickCheck保持了Gen是概率分布的假象,并且不允许您区分具有相同分布的两个生成器.
此模块中的函数允许您通过重复使用相同的随机数种子两次来打破这种错觉.这是不安全的,因为通过将相同的种子应用于两个在道德上相等的发电机,您可以看到它们是否真的相等.