Haskell QuickCheck独特的随机数生成技术

4
有人知道如何使用QuickCheck在Haskell中定义生成器,以便仅选择一次选择的元素吗?
我已经意识到可能需要一个“Gen(Maybe Positive)”生成器,但是这样会生成具有重复的数字。 我希望所选数字不会重复。 在返回数字时,我希望返回Just,在随机数全部用完时,我希望返回Gen Nothing。
谢谢, 马克
3个回答

5
您无法这样做。查看 Gen的定义。它没有任何方式来携带关于已选内容的状态。给定相同的随机生成器和大小限制,它必须始终生成相同的结果。但是,您可以编写一个Eq a => Gen [a],它会生成没有重复值的值列表。一个简单(但有些幼稚)的方法可能是像这样的东西。
uniques :: Eq a => Gen a -> Gen [a]
uniques gen = fmap nub $ listOf gen

2
xorshift 随机生成器从设计上来说没有重复。你可以尝试一下。(上述语句适用于前2^64个数字左右。) - fuz
哦,我认为可以通过使用CoArbitrary(以某种方式?)每次选择不同的生成器,并受到范围限制/约束。 - Mark

3

QuickCheck通常用于随机测试,而不是详尽测试。有一些很棒的库可以处理详尽测试——看一下smallchecklazysmallcheck


0

你可以使用模块 Data.List 中的 permutations 函数来实现。

下面是 permutations 函数的函数签名:

permutations :: [a] -> [[a]]

如你所见,它返回一个列表的列表。这里有一个小例子(使用 GHCi 7.0.4):

> permutations [1..3]
[[1,2,3],[2,1,3],[3,2,1],[2,3,1],[3,1,2],[1,3,2]]

因此,你可以这样做:

prop_unique_elements = forAll (elements (permutations [1..3])) $ \x -> foo == bar

我没有测试过,所以需要一些调整,但我希望它能清楚地传达重点。祝你好运。


我认为forall并不是你想象中的那样。 - sclv
@sclv 我认为它是在声明生成器对谓词的全称量化。:) 它显然不会详尽地运行每个排列一次,但是生成器的每个结果都将是一个具有唯一元素的列表,正如问题所问。 - Brandon
那么我们只是对问题有不同的理解 - 我的理解是要求进行详尽的测试 - 即为每个测试选择一个不同的元素,而不是要求生成器为每个测试生成包含不同元素的列表,但可能在不同的测试中生成相同的列表。 - sclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接