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

Adding static files to Yesod

Planning a simple Reddit clone with Yesod

React-router-dom bindings for Reason

Parsing complex foreign objects in PureScript

A way to deal with big objects and FFI.

Post requests with PureScript Affjax and Argonaut

Simple ajax calls to an API example

Functor, Applicative e Monad illustrati

Una guida chiara

PureScript Impressions

Trying to put some sense in JavaScript

Clojure Examples

Toggling DELL 9350's touchpad on Ubuntu 15.10

How to set up a hotkey to toggle DELL 9350's touchpad on Ubuntu 15.10

Using the Asus MB168B+ with Ubuntu 15.10

How to edit the driver install script to make it work on Ubuntu 15.10+ (and other distros)