Following the amazing Haskell Programming book, I was stuck for a while on the Monad chapter.

An exercise asks to write a List data type, implement its Functor, Applicative and Monad instances and then test them with QuickCheck and Checkers.

Having this data type:

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


I had write its Arbitrary instance to generate values for the tests.

There’s a useful function in QuickCheck called sized that can be used for this.

The type signature is:

sized :: (Int -> Gen a) -> Gen a


What’s needed to use it is a function that takes a Int and returns a Gen a.

This is the function I ended up with:

arbitraryList :: Arbitrary a => Int -> Gen (List a)
arbitraryList m
| m == 0 = return Nil
| m > 6 = arbitraryList 6
| otherwise = Cons <\$> arbitrary <*> (arbitraryList (m-1))


I capped the length at 6 to avoid super long lists.

The Arbitrary instance is then:

instance Arbitrary a => Arbitrary (List a) where
arbitrary = sized arbitraryList