我为此代码运行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分钟。所以我想知道这种行为是从哪里来的,也许我能以某种方式看到生成的值。
我们可以计算具有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,但includesNil
元素)。因此,这意味着如果将k设置为499
,则平均将生成499个元素的列表,而如果将k
设置为2
,则将生成平均长度为2的列表。当然,计算工作量取决于列表的长度。