Search code examples
haskellquickcheck

How to generate arbitrary instances of a simple type for quickcheck


I have a simple type definition:

data Cell = Cell {
    x       :: Int,
    y       :: Int
  } deriving (Show)

I can't use Cell as an input to a quickcheck property, presumably because quickcheck doesn't know how to generate Cell values.

My understanding is that I need to make Cell an instance of the Arbitrary typeclass.

How do I do that, for example, if I'd like Cell to be generated with random positive values for x and y?


Solution

  • Writing an instance of Arbitrary for your data type is easy. You just have to implement the arbitrary function, which should return a Gen Cell. The simplest way to do this is to make use of existing Arbitrary instances and also note that Gen is a monad, so we can use do-notation:

    instance Arbitrary Cell where
       arbitrary = do
         Positive x <- arbitrary
         Positive y <- arbitrary
         return $ Cell x y
    

    Alternatively, generators can often be written elegantly using operators from Control.Applicative:

    instance Arbitrary Cell where
       arbitrary = Cell <$> pos <*> pos
         where pos = getPositive <$> arbitrary  -- getPositive requires QC >= 2.5
    

    Here, I've also made use of the Positive modifier from Test.QuickCheck.Modifiers to ensure that we only generate positive integers.

    For writing more complex generators, have a look at the various generators from Test.QuickCheck.Gen.