you can use oneof to select either an empty list or recursively generate longer lists:
instance Arbitrary a => Arbitrary (List a) where arbitrary = oneof [nil, cons] where nil = return Nil cons = do h <- arbitrary tl <- arbitrary return $ Cons h tl
here are some tests:
λ> generate (arbitrary :: Gen (List Int)) Nil λ> generate (arbitrary :: Gen (List Int)) Cons 4 (Cons 26 Nil) λ> generate (arbitrary :: Gen (List Int)) Nil
remarks
As zeta has shown, this has an obvious flaw that you will create, probably very short lists:
- p (Nil) = 0.5
- p ((_
Cons Nil) = 0.25 - p ((_
Cons _ Cons Nil) = 0.125 - ...
how he draws Nil with a probability of 0.5
Zetas solution does not have this problem!
You can adapt this probability using frequency instead of oneof if you want:
frequency [(1,nil), (4,cons)]
here you will have p(Nil) = 0.2 and p(Cons) = 0.8 , but of course you can adapt this to your liking.
Another way is to understand that List a is isomorphic [a] and reuse an Arbitrary instance for lists:
instance Arbitrary a => Arbitrary (List a) where arbitrary = toList <$> arbitrary
Thank you Zeta strong>
source share