【发布时间】:2018-02-11 11:31:20
【问题描述】:
我正在尝试使用 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 的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)
我正在尝试做类似的事情,除了生成两个-参数任意函数。
如何生成两个参数函数的任意实例,以便对 zipWith 等高阶函数进行 QuickCheck 测试?
【问题讨论】:
-
你不能仅仅利用柯里化并使用
Fun Int (Fun Int Int)吗?请记住,没有二进制函数这样的东西,因为一切都是柯里化的。 -
请注意语句“这不起作用,因为 (Int -> Int -> Int) 不是 Arbitrary 的实例。”为假(函数 是 的任意实例)。它不起作用,因为函数不是
Show的实例。但正如@chi 所说,currying 以一种微不足道的方式解决了你的问题(而且也以Fun (Int, Int) Int也可以工作的唯一稍微不那么微不足道的方式)。您可能会发现unFun (Fun _ f) = f; unFun2 f = unFun . unFun f的定义很有用。 -
@chi,我有限的实践经验表明,
Fun (a,b,...) x比Fun a (Fun b (... x ...))工作起来更痛苦 -
如果您的下一个问题是“高阶函数呢?”,那也是我的问题。但这似乎非常困难。 Koen Claessen 无法找到令人满意的解决方案,因此您应该仅在需要研究项目时才考虑它。
标签: haskell quickcheck