简体   繁体   English

如何在Haskell Test.QuickCheck中有效地生成随机测试

[英]How to efficiently generate random tests in Haskell Test.QuickCheck

I'd like to generate some sample tests using Haskell Test.QuickCheck 我想使用Haskell Test.QuickCheck生成一些示例测试

The goal is to generate data of (Int, [Int]) with the following conditions where the tuple is (x, xs): 目标是使用以下条件生成(Int,[Int])的数据,其中元组是(x,xs):

  1. x > 0 x> 0
  2. x not in xs x不在xs中
  3. all xs >0 所有xs> 0

Scratching my head and stumbling through the manual https://github.com/stackbuilders/quickcheck-manual after some time I can produce random lists meeting these requirements: 经过一段时间后,我可以抓住我的脑袋并绊倒手册https://github.com/stackbuilders/quickcheck-manual ,我可以生成符合这些要求的随机列表:

import Test.QuickCheck
mygen = arbitrary::Gen (Int, [Int]))
sample (mygen `suchThat` ( \(x, xs)->( (x `notElem` xs) && (x > 0) && (all (>0) xs)&& (xs/=[]))))

Running the last line in the GHCI outputs something like: 在GHCI中运行最后一行输出如下:

(40,[19,35,27,29,45,1,17,28])
(20,[3,9,11,12,15,8])
(43,[76,102,106,71,24,2,29,101,59,48])
(99,[5,87,136,131,22,22,133])
(77,[11,14,55,47,78,15,14])
...

Questions: 问题:

  1. How can this be done more efficiently since - I'm guessing- the function mygen creates a large sample set then filters out based on the suchThat criteria 这该如何更有效地完成,因为-我guessing-功能mygen创建基于设置的再大样本过滤掉suchThat标准

  2. How can I indicate the list xs should be of a certain size. 如何指示列表xs应该具有一定的大小。 For example if I add && length xs > 50 the program runs for a very long time. 例如,如果我添加&& length xs > 50 ,程序会运行很长时间。

  3. Guarantee that each element of xs is unique. 保证xs的每个元素都是唯一的。 Ie avoid records like (99,[22,22]) 即避免像(99,[22,22])这样的记录

Yeah, assuming the probability that a generated number is positive is 1/2, then the probability of getting a list of 50 positive numbers is (1/2)^50, or 1 in 1,125,899,906,842,624. 是的,假设生成的数字为正数的概率是1/2,那么获得50个正数列表的概率是(1/2)^ 50,或1,125,899,906,842,624中的1。 So yeah, that's not gonna happen. 所以,是的,那不可能发生。

Instead of generating lists and filtering them, I would suggest building lists you need by transforming generators. 我建议不要生成列表并过滤它们,而是建议通过转换生成器来构建列表。

mygen :: Gen (Int, [Int])
mygen = do 
    x <- getPositive <$> arbitrary
    xs <- delete x <$> replicateM 50 (getPositive <$> arbitrary)
    return (x, xs)

Now you are guaranteed to get a list matching your criteria immediately. 现在,您可以立即获得符合条件的列表。

As for uniqueness, see Data.List.nub . 至于唯一性,请参阅Data.List.nub You might also consider using a Data.Set , since it seems you are using it that way. 您也可以考虑使用Data.Set ,因为您似乎正在使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM