我为此代码运行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)))
当任意权重为1和2时,所有测试加在一起需要5秒才能完成。但是,当我将权重设置为1和499时(一次取零,而实际值取499次,对吗?),所有测试都变慢了,特别是每个适用成分测试需要5分钟。所以我想知道这种行为是从哪里来的,也许我能以某种方式看到生成的值。
答案 0 :(得分:1)
我们可以计算具有 n 个元素的列表的概率分布。如果您实现它:
instance Arbitrary a => Arbitrary (List a) where
arbitrary = frequency [(1, return Nil), (k, Cons <$> arbitrary <*> arbitrary)]
然后有 1 /(1 + k)列表终止。请注意,黑体字arbitrary
是您在此处定义的任意值,因此您进行了 recursive 调用。因此,这意味着长度为 n 的列表的可能性为:
P(| L | = n)= k n-1 /(1 + k) n
这是Gemetrical distribution [wiki],列表的平均长度为 k (“几何分布”变量的平均值为 k + 1 ,但包括 Nil
元素)。因此,这意味着,如果将 k 设置为499
,则平均会生成499个元素的列表,而如果将k
设置为2
,它将会生成平均长度为2的列表。当然,计算量会根据列表的长度进行缩放。