【问题标题】:How to efficiently generate random tests in Haskell Test.QuickCheck如何在 Haskell Test.QuickCheck 中高效地生成随机测试
【发布时间】:2017-03-01 03:27:51
【问题描述】:

我想使用 Haskell Test.QuickCheck 生成一些示例测试

目标是生成 (Int, [Int]) 的数据,其中元组为 (x, xs) 的条件如下:

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

一段时间后,我摸不着头脑并跌跌撞撞地翻阅手册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/=[]))))

在 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])
...

问题:

  1. 如何才能更有效地做到这一点,因为 - 我猜 - 函数 mygen 创建一个大样本集,然后根据 suchThat 标准过滤掉

  2. 如何指示列表 xs 应具有特定大小。例如,如果我添加&& length xs > 50,程序会运行很长时间。

  3. 保证 xs 的每个元素都是唯一的。 IE。避免像 (99,[22,22]) 之类的记录

【问题讨论】:

    标签: haskell testing random quickcheck


    【解决方案1】:

    是的,假设生成的数字为正数的概率为 1/2,那么得到 50 个正数列表的概率为 (1/2)^50,即 1,125,899,906,842,624 中的 1。所以,是的,这不会发生。

    我建议不要生成列表并过滤它们,而是通过转换生成器来构建您需要的列表。

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

    现在您可以保证立即获得符合您条件的列表。

    至于唯一性,请参阅Data.List.nub。您也可以考虑使用Data.Set,因为您似乎正在使用它。

    【讨论】:

    • abs &lt;$&gt; arbitrary 仍然可以产生0。您可以使用positive = getPositive &lt;$&gt; arbitrary 仅生成正数。
    • xs 的生成器创建一个最多包含 50 个元素的列表,而不是至少 50 个元素。对于至少 50 个元素,您可以执行类似 n &lt;- getNonNegative &lt;$&gt; arbitrary; xs &lt;- replicateM (n+50) (arbitrary `suchThat` (/= x)) 的操作。
    • 谢谢!有见地。有没有办法保证 xs 包含 50 个元素?如果我执行 nub.delete 之类的操作...mygen = do x &lt;- getPositive &lt;$&gt; arbitrary xs &lt;- nub.delete x &lt;$&gt; replicateM 50 (getPositive &lt;$&gt; arbitrary) return (x, xs) 返回相当小的列表 (1,[1,2,3]) (2,[2,1,3]) (1,[4,1,3,2]) (4,[3,2,1,6,5,4]) (7,[1,2,8,6,5,7,4,3]),因为许多元素都被丢弃了...
    • @brander,嗯,您也许可以为此使用范围更小的suchThat。说(getPositive &lt;$&gt; arbitrary) `suchThat` (`notElem` alreadyGenerated) -- 以alreadyGenerated 作为累加器递归。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-25
    相关资源
    最近更新 更多