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)
楠:+楠
关键点基本上是所有1Real
类型都有额外的规则,特别是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
上使用
,这是一个要点。我没有预先从你的问题中读到你想把这些财产计算出来。