Arbitrary length lists with QuickCheck


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

Related Posts

Resizing and moving windows in Doom Emacs

Setting up TabNine on Doom Emacs

The correct docker-compose setup for Wordpress and Nginx

Adding a newline after a comment block in Doom Emacs

PureScript Date and Time guide

Adding live css and js reload to Yesod

A quick overview of Purescript package managers as of October 2018

Optional elements and properties in Halogen

Simple AJAX in Purescript

Automatically adding (or removing) a prefix to a record labels in Purescript