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
?
Fun Int (Fun Int Int)
? Remember that there's no such a thing as a binary function, since everything is curried. – chiShow
. But as @chi says, currying solves your problem in a trivial way (and also in the only slightly less trivial way thatFun (Int, Int) Int
would work as well). You may find the definitionsunFun (Fun _ f) = f; unFun2 f = unFun . unFun f
useful. – user2407038Fun (a,b,...) x
is less painful to work with thanFun a (Fun b (... x ...))
– dfeuer