How does QuickCheck detect datatypes?
如果我们定义这样的函数
1 |
然后运行
1 | quickCheck fun |
quickCheck开始生成Int类型的随机数据。问题是quickCheck如何检测到fun的参数数据类型是Int而不是其他任何数据类型?如果我让这个问题更笼统,我应该问我们是否有一个名为fun的函数,像这样
1 | fun :: datatype_1 -> datatype_2 -> ... -> datatype_n -> Property |
quickCheck如何检测每个单独的数据类型_1,数据类型_2,...和数据类型_n的类型?以及它如何检测功能fun需要多少个参数?
大致上,这就是类型类的工作方式。一个人可以声明
1 2 |
然后
1 2 3 4 5 6 |
以此类推。
这显然具有使
当然,实际的QuickCheck机制要复杂得多。为了处理带有任意数量参数的函数,可以使用一组"递归"
晚了一点,但这是您在当前实现中正在寻找的实例。
1 2 3 4 5 6 7 8 9 10 11 | instance (Arbitrary a, Show a, Testable prop) => Testable (a -> prop) where property f = propertyForAllShrinkShow arbitrary shrink (return . show) f propertyForAllShrinkShow gen shr shw f = -- gen :: Gen b, shr :: b -> [b], f :: b -> a -> prop -- Idea: Generate and shrink (b, a) as a pair propertyForAllShrinkShow (liftM2 (,) gen arbitrary) (liftShrink2 shr shrink) (\\(x, y) -> shw x ++ [show y]) (uncurry f) |
正如@chi正确指出的那样,这里发生了递归。递归调用是