QuickCheck: defining Arbitrary instance in terms of other Arbitraries

2.2k Views Asked by At

I'm using QuickCheck 1 and I've got the following data types:

data A = ...
instance Arbitrary A where ...
data B = ...
instance Arbitrary B where ...
data C = C A B

Now I'd like to define an Arbitrary instance for C so that C values are generated using existing generators for A and B. I ended up doing this:

instance Arbitrary C where
  arbitrary = elements [(C a b) |
                        a <- generate 20 (System.Random.mkStdGen 0) arbitrary,
                        b <- generate 20 (System.Random.mkStdGen 0) arbitrary]

Is this explicit generation of a fixed number of values for A and B necessary, or is there a better way of combining existing Arbitraries into a new one?

1

There are 1 best solutions below

3
On BEST ANSWER

I'd do it like this:

instance Arbitrary C
  where arbitrary = do a <- arbitrary
                       b <- arbitrary
                       return (C a b)

Although sclv's idea of using liftM2 from Control.Monad is probably better:

instance Arbitrary C
  where arbitrary = liftM2 C arbitrary arbitrary