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?
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.