[Haskell-beginners] Managing boilerplate code in QuickCheck properties...

Stuart Hungerford stuart.hungerford at gmail.com
Fri Apr 10 22:17:13 UTC 2015


Hi,

I'm using the wonderful QuickCheck and Tasty libraries to test a bunch
of properties (actually axioms for typeclasses):

positivity_suite :: TestTree
positivity_suite = testGroup "positivity axiom" [

  testProperty "Float"
    (axiom_positivity :: Float -> Bool),

  testProperty "(Float, Float)"
    (axiom_positivity :: (Float, Float) -> Bool),

 -- etc  ]



symmetry_suite :: TestTree
symmetry_suite = testGroup "symmetry axiom" [

  testProperty "Float"
    (axiom_symmetry :: Float -> Float -> Bool),

  testProperty "(Float, Float)"
    (axiom_symmetry :: (Float, Float) -> (Float, Float) -> Bool),

  -- etc ]


Over multiple typeclasses, axioms and instance types this leads to a
huge amount of repeated, boilerplate code. I asked an earlier question
on the Haskell Cafe mailing list about testing polymorphic typeclasses
in QuickCheck but I'm realizing the issue is going to crop up beyond
testing typeclass axioms and perhaps beyond testing. I can see several
workarounds for managing the boilerplate code:


1. Define a set of CPP macros for the property type signatures

2. Do the same sort of thing with Template Haskell but with mapping
over a list of desired test types

3. Define a very tedious but succinct set of type aliases allowing
most properties to become more cryptic one-liners


type Pr_F_F = Float -> Float -> Bool

type Pr_F2_F2 = (Float, Float) -> (Float, Float) -> Bool

-- etc, then

testProperty "(Float, Float)"  (axiom_symmetry :: Pr_F2_F2)


How do experienced Haskellers deal with this situation?  I feel I'm
missing something in how I've gone about this.


Thanks,

Stu


More information about the Beginners mailing list