首页 > 解决方案 > QuickCheck 如何检测数据类型?

问题描述

如果我们定义一个这样的函数

fun :: Int -> Property

然后运行

quickCheck fun

quickCheck 开始生成 Int 类型的随机数据。问题是 quickCheck 如何检测 fun 的参数数据类型是 Int 而不是任何其他数据类型?如果我把问题说得更笼统,我应该问一下,如果我们有这样一个叫做 fun 的函数

fun :: datatype_1 -> datatype_2 -> ... -> datatype_n -> Property

quickCheck 如何检测每个单独的 datatype_1、datatype_2、... 和 datatype_n 的类型?还有它如何检测函数 fun 需要多少个参数?

标签: haskellquickcheck

解决方案


粗略地说,这就是类型类的工作方式。可以申报

class C a where
   foo :: a -> Bool

接着

instance C (Int -> Bool) where
   foo f = f 42
instance C (String -> Bool) where
   foo f = f "hello"
instance C (String -> [Int]) where
   foo f = sum (f "hello") > 42

等等。

这具有明显的效果,可以foo“检测”其参数的类型f并采取相应的行动。实际上,发生的事情是 Haskell 执行类型推断,在此期间选择适当的实例——在编译时。在运行时,不会发生“类型检测”;实际上,类型在编译后会被擦除,并且在运行时没有可用的类型信息,因此无法检测到f属于哪个类型。

当然,实际的 QuickCheck 机制要复杂得多。为了处理具有任意数量参数的函数,使用了一组“递归instance”,可以说,每次“递归调用”处理每个参数。这是一种相当棘手的技术,也用于printf其他“可变参数”函数。如果您不熟悉类型类,我不建议您从如此复杂的技巧开始学习它们。


推荐阅读