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 warn开发者_StackOverflow中文版ing 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.
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)
The import Text.Show.Functions
could also be used with keeping the original signature.
精彩评论