Recursive types in QuickCheck

I want to build arbitrary sized trees of Compound

data Compound = And Compound Compound
  | Or Compound Compound
  | Product Compound Compound
  | Not Compound
  | Leaf { diagram :: Unitary} deriving (Show, Eq)

However, I want to limit to a max depth, and I want to have each branch to be of an arbitrary depth.

mkBinary :: (Compound -> Compound -
> Compound) -> Int -> Gen Compound
mkBinary f depth =
  liftM2 f (mkCompound depth') (mkCompound depth')
  where
    depth' = depth -1

mkNot :: Int -> Gen Compound
mkNot depth =
  liftM Not (mkCompound (depth-1))

mkLeaf :: Gen Compound
mkLeaf = liftM Leaf arbitrary

mkCompound :: Int -> Gen Compound
mkCompound 0 = mkLeaf
mkCompound depth = oneof [mkLeaf, mkBinary And depth, mkBinary Or depth, mkBinary Product depth, mkNot depth]

instance Arbitrary Compound where
  arbitrary =
    do depth <- choose (0, 4)
       d <- mkCompound depth
       return d

QuickCheck can do it. It’s nice. Use it.

Leave a Reply