我正在尝试使用QuickCheck测试zipWith
的实现。我的实现myZipWith
,我希望通过与标准函数进行比较来进行QuickCheck测试。类似的东西:
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)
这不起作用,因为(Int -> Int -> Int)
不是Arbitrary
的实例。
使用单参数函数,可以使用Test.QuickCheck.Function
' s Fun
(实例化Arbitrary
)来解决这个问题。例如:
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)
我正在尝试做类似的事情,除了生成两个 -argument任意函数。
如何生成两个参数函数的任意实例,以便对zipWith
等高阶函数进行QuickCheck测试?
答案 0 :(得分:4)
使用QuickCheck 2.9.2,您可以使用Fun
类型和Fn
模式。你必须
import Test.QuickCheck.Function
然后,您可以使用元组作为输入来编写属性,然后使用curry
函数:
prop_myZipWith :: Eq c => Fun (a, b) c -> [a] -> [b] -> Bool
prop_myZipWith (Fn f) x y = myZipWith (curry f) x y == zipWith (curry f) x y
main
看起来像这样:
main =
quickCheck (prop_myZipWith :: Fun (Int, Int) Int -> [Int] -> [Int] -> Bool)
这个编译,测试通过,在我的repro。
使用QuickCheck 2.10.0.1,您可以使用Fn2
模式,如下所示:
prop_myZipWith :: Eq c => Fun (a, b) c -> [a] -> [b] -> Bool
prop_myZipWith (Fn2 f) x y = myZipWith f x y == zipWith f x y
主要方法保持不变,因为prop_myZipWith
的类型没有改变,但不再需要import Test.QuickCheck.Function
。