11
votes

I'm trying to write a QuickCheck property that takes one or more functions as input. To keep things simple, consider a property to check that function composition is equivalent to successive function application, and a quick-and-dirty test driver:

import Test.QuickCheck

prop_composition :: (Int -> Int) -> (Int -> Int) -> Int -> Bool
prop_composition f g x = (f . g) x == f (g x)

main :: IO ()
main = quickCheck prop_composition

Unfortunately, this doesn't compile, because the inputs to a property need to implement Show so that QuickCheck can report what inputs caused the failure, but there's no Show implementation for functions:

Test.hs:10:7:
    No instance for (Show (Int -> Int))
      arising from a use of `quickCheck' at Test.hs:10:7-33
    Possible fix: add an instance declaration for (Show (Int -> Int))
    In the expression: quickCheck prop_composition
    In the definition of `main': main = quickCheck prop_composition

I've tried writing my own do-nothing instance of Show for functions...

instance Show (a -> b) where
    show _ = "[func]"

... which compiles, but triggers a warning with -Wall...

Test.hs:3:9: Warning: orphan instance: instance Show (a -> b)

... which makes me think there's a more correct way to do this.

My gut tells me the answer lies in the Test.QuickCheck.Function module, but it's undocumented, and I can't figure out just from looking at the type signatures what anything in there is for or how it's intended to be used.

2

2 Answers

10
votes

You are right Test.QuickCheck.Function is the right answer. You just change the types:

prop_composition       :: Fun Int Int -> Fun Int Int -> Int -> Bool
prop_composition f g x = ((apply f) . (apply g)) x == (apply f) ((apply g) x)
3
votes

The import Text.Show.Functions could also be used with keeping the original signature.