Managing boilerplate code in QuickCheck properties...

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
participants (1)
-
Stuart Hungerford