I am trying to test my implementation of zipWith using QuickCheck. My implementation, myZipWith, I would like to QuickCheck test by comparing to the standard function. Something like:
main = do
quickCheck (prop_myZipWith :: (Int -> Int -> Int) -> [Int] -> [Int] -> Bool)
prop_myZipWith :: (a -> b -> c) -> [a] -> [b] -> Bool
prop_myZipWith f x y = (myZipWith x y) == (zipWith f x y)
This does not work because (Int -> Int -> Int) is not an instance of Arbitrary.
With single-argument functions one can get around this using Test.QuickCheck.Function's Fun (which instantiates Arbitrary). For example:
main = do
quickCheck (prop_myMap :: Fun Int Int -> [Int] -> Bool)
prop_myMap :: Fun a b -> [a] -> Bool
prop_myMap (Fun _ f) l = (myMap f l) == (map f l)
I am trying to do something similar except generating two-argument arbitrary functions.
How can I generate arbitrary instances of two argument functions for QuickCheck testing of higher-order functions such as zipWith?
QuickCheck 2.9.2
With QuickCheck 2.9.2, you can use the
Funtype, and theFnpattern. You'll have toYou can then write the property using a tuple as input, and then
currythe function:mainlooks like this:This compiles, and the test passes, in my repro.
QuickCheck 2.10.0.1
With QuickCheck 2.10.0.1, you can instead use the
Fn2pattern, like this:The main method remains the same, because the type of
prop_myZipWithhasn't changed, butimport Test.QuickCheck.Functionis no longer required.