有没有办法显示为 quickCheck 和 quickBatch 生成的值

Is there a way to show values which are generated for quickCheck and quickBatch

我 运行 quickBatch 测试此代码:

data List a = 
    Nil 
  | Cons a (List a) 
  deriving (Eq, Show) 

instance Functor List where
  fmap _ Nil         = Nil
  fmap f (Cons a as) = Cons (f a) (fmap f as)

instance Applicative List where
  pure a = Cons a Nil
  Nil <*> _ = Nil
  _ <*> Nil = Nil
  (Cons f fs) <*> as = fmap f as `append` (fs <*> as)

append :: List a -> List a -> List a
append Nil ys         = ys
append (Cons x xs) ys = Cons x $ xs `append` ys

instance Arbitrary a => Arbitrary (List a) where
  arbitrary = frequency [(1, return Nil), (2, Cons <$> arbitrary <*> arbitrary)]

main :: IO ()
main =
  hspec $ do
    describe "List" $ do
      it "Functor" $
        property (quickBatch $ functor (undefined :: List (Int, Float, String)))
      it "Applicative" $
        property (quickBatch $ applicative (undefined :: List (Int, Float, String)))

当 Arbitrary 的权重为 1 和 2 时,所有测试总共需要 5 秒才能完成。但是,当我将权重设置为 1 和 499(Nil 取一次,实际值取 499 次,是否正确?)时,所有测试都比较慢,尤其是每个应用组合测试需要大约 5 分钟。所以我想知道这种行为从何而来,也许我能以某种方式看到生成的值。

我们可以计算具有 n 个元素的列表的概率分布。如果你实施它:

instance Arbitrary a => Arbitrary (List a) where
    arbitrary = frequency [(1, return Nil), (<i>k</i>, Cons <$> arbitrary <*> <b>arbitrary</b>)]

则有1/(1+k)表示列表终止。请注意,粗体字的 arbitrary 是您在此处定义的任意值,因此您进行了 递归 调用。因此,这意味着长度为 n 的列表的可能性为:

P(|L|=n) = kn-1/(1+k)n

这是一个Gemetrical distribution [wiki],列表的平均长度将是k(几何分布变量的平均值是 k+1,但 包含 Nil 元素)。所以这意味着如果你将 k 设置为 499,你将平均生成一个包含 499 个元素的列表,而如果你将 k 设置为 2, 它生成平均长度为 2 的列表。当然,计算量会随着列表的长度而增加。