Generics 泛型函数的正确性证明/测试

Generics 泛型函数的正确性证明/测试,generics,haskell,quickcheck,Generics,Haskell,Quickcheck,(这不是关于定理证明,而是关于实践中的测试,如quickCheck) 让f使用一些泛型函数 f :: RESTRICTIONS => GENERICS 具有一些“理想的”属性(即不是hack,是不可变的,…)通常是纯Haskell泛型函数 假设我们想要测试它,主要问题是 如果我们已经(很好地)测试了一种特定类型的函数(例如,Int),我们可以假设它适用于所有类型吗?(当然,匹配限制) (使用“经过良好测试”我是指“所有”函数{domain X properties}已经过测试) 理论上,

(这不是关于定理证明,而是关于实践中的测试,如
quickCheck

f
使用一些泛型函数

f :: RESTRICTIONS => GENERICS
具有一些“理想的”属性(即不是hack,是不可变的,…)通常是纯Haskell泛型函数

假设我们想要测试它,主要问题是

如果我们已经(很好地)测试了一种特定类型的函数(例如,
Int
),我们可以假设它适用于所有类型吗?
(当然,匹配限制)

(使用“经过良好测试”我是指“所有”函数
{domain X properties}
已经过测试)

理论上,我们可以确定,但是,我不确定是否有一些额外的属性,限制。。。在实例化过程中(即编译)可能会产生影响

谢谢

注意测试可能使用特定类型的属性(例如
Int
),但这些属性不能是测试属性的一部分。例如,如果
Monoid
是一个限制,则结合性可以是测试属性的一部分(但如果不是限制,则不是交换性)

示例

f

repeatedHeader :: Eq a => [a] -> Bool
repeatedHeader (x:y:_) = x == y
repeatedHeader _ = False

test1 = repeatedHeader [1,1,2] == True
test2 = repeatedHeader [1,2,3] == False
不,你不能肯定

考虑

f :: (Fractional a) => a -> a
f x = (2 * x^2 + 2) / (x^2 + 1)
你现在会说,显然
fx≡ 2
。果然

序曲>地图f[-2,-1.6..3]
[2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0,2.0]

事实上,它确实适用于所有
Rational
参数,以及任何非超限实数类型。但是,当您允许更一般的
分数类型时,它很容易被破坏:

序曲数据.Complex>f(0:+1)
楠:+楠

关键点基本上是所有1
Real
类型都有额外的规则,特别是
x^2>=0
,这不适用于一般的
Num
情况


一个更好的例子可能是

g :: Num a => a -> a
g = (+1)
直观地说,
gx>x
,它适用于所有
Integer
s。但事实并非如此

前奏曲数据。模块>地图((x:):ℤ/5) ->gx>x).fromInteger)[0..10]
[真,真,真,真,假,真,真,真,真,真,假,真]



1在考虑数字问题时,例如,
Double

您可以确保,只有在很小的情况下,限制是空的,或者至少没有提到所讨论的泛型类型

在所有其他情况下,函数取决于类型类实例的功能。但是,即使所有现有的实例都按照您期望的方式运行,对于明天编写的类型类实例也不一定是这样

因此,这是一个在实例中强制执行某些属性的问题。这通常是一个弱点,因为类型类法则大多只是非正式地陈述。例如,Haskell不能也不会阻止您生成错误的Eq或Ord实例

一个真实的例子是对函数的测试,如:

f :: Num a => a -> a

现在,我们知道我们确实有一些类型可以无声地溢出,比如Int,而其他类型则没有。这在Num类中是被默默地容忍的,因为,好吧,生活就是这样。因此,使用
Double
完成所有测试后,如果在
Int

前提
fx上使用
f
,您仍然会感到惊讶≡ 2
不正确(即您的第一次测试不正确)。。。“所有”函数{domain X properties}已经过测试…@josejuan:我没有明确说明使用了什么类型,但是,很明显,我指的是“真正的”类型
Rational
是标准库中唯一精确的一个;满足
fx≡ 2
用于所有可能的值,这一点可以很容易地证明。您不能(不应该)仅对所有可能类型的非限制子集执行泛型函数(如果愿意,请添加限制)。你不能承认
1/(x^2+1)
的存在,只知道
是分数的,因此,得出
fx=2
是不正确的结论。这同样适用于
Num
,如果您希望为所有
x
得出
gx>x
的结论,则需要
TotalOrder
g
函数进行限制。我发现很难获得所有类依赖项的可靠定义(正如@ingo所写)。无论如何谢谢你@我不同意。
f
的复杂实例化是完全合理的(也许不是为了这个人为的常量,但对于在复杂平面中具有实际极点的函数来说已经足够了)。它确实有这个丑陋的未定义的点;我们希望通过类型系统计算出来,但不幸的是,这是不可行的。-你不能像Agda/Idris/Coq那样深入研究Haskell中的证明,我认为通常也没有必要(你也可以使用这些助手来证明用其他语言编写的程序)。关于在非
TotalOrder
上使用
,这是一个要点。我没有预先从你的问题中读到你想把这些财产计算出来。