HASKELL:验证打字机中的函数的每个实现都是交换的
假设我们有一个函数f ::(t a)=> a - > a - > a - >在Typeclass t中,类型类别具有多种类型的实例。 假设我们希望此功能不管给定类型的实现如何,即 ∀a,b∈X:(tx,eq x)=> ∃f x - > X - > x,fab == fb a
如果我要验证更具体的情况的通勤性,请说(+)和int,我可以写下这样的内容:
import Test.Quickcheck (quickCheck)
commutativityProperty :: Eq a => (a -> a -> a) -> a -> a -> Bool
commutativityProperty f a b = f a b == f b a
main :: IO ()
main = do
quickCheck (commutativityProperty (+) :: Int -> Int -> Bool)
QuickCheck不适合模棱两可的类型变量,因此我无法写下这样的内容: QuickCheck(commutativityproperty(+)::(num a,eq a)=> a - > a - > bool)
或者,对于更一般的情况: QuickCheck(commutativityProperty f ::(t a,eq a)=> a - > a - > bool)
问题是: 在类似的上下文中,我知道此功能必须保持通勤性,而不论特定类型的实现如何,我如何验证这确实是正确的,而无需为实现F的每种类型编写Quickcheck行并必须维护该代码(即,每当创建具有T的新类型时,我都必须回来为该特定类型编写新行)吗?
Suppose we have a function f :: (T a) => a -> a -> a -> in a typeclass T, typeclass which has instances in numerous types.
Suppose we want this function to be commutative regardless of its implementation for a given type, i. e.∀ a, b ∈ X: (T X, Eq X) => ∃ f X -> X -> X, f a b == f b a
If I were to verify commutativity for a more concrete case, let`s say (+) and Int, I could write something like this:
import Test.Quickcheck (quickCheck)
commutativityProperty :: Eq a => (a -> a -> a) -> a -> a -> Bool
commutativityProperty f a b = f a b == f b a
main :: IO ()
main = do
quickCheck (commutativityProperty (+) :: Int -> Int -> Bool)
quickCheck does not work with ambiguous type variables, so I could not write something like this:quickCheck (commutativityProperty (+) :: (Num a, Eq a) => a -> a -> Bool)
Or, for the more general case:quickCheck (commutativityProperty f :: (T a, Eq a) => a -> a -> Bool)
The Question is:
In a similar context, where I know this function must hold commutativity regardless of implementation for a specific type, how can I verify that this is indeed true without having to write a line of quickCheck for every type that implements f and have to maintain that code (i.e. every time a new type with an instance of T is created, I would have to come back and write a new line for that specific type)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
想到了两种方法:
使用GADT生成随机类型
,您可以尝试生成“随机类型”,并将其用于测试您的多态函数。这并不是完全容易的,但是根据您的类型,它仍然可行。
给您一个非常粗略的草图:
测试非全能类型的类型可能是免费的!
每当我们具有(终止)多态功能时,我们都会知道它可以满足一个称为 免费定理 (口号是“免费的”定理!”)。例如,如果我们具有
f :: a-> a
必须是身份,而g :: a-> a-> a
必须是<代码> \ x y-&gt; x 或\ x y-&gt; y
。添加像您的t a
这样的类型约束使其更加复杂,但是仍然可以生成免费定理。使用这种免费定理,您可能会证明,如果您的属性保留了整数,则必须在类
t
中保留任何类型的类型。我给你一个例子。假设
f :: ord a =&gt; [a] - &gt; [a]
正确分类整数。然后,通过自由定理,它也对任何其他完全有序的类型进行分类。直观地,这是因为f
无法真正检查输入列表的元素,除了使用比较(&lt;
,比较
,...) 。因此,如果将列表元素替换为具有完全相同的比较结果的合适整数,则f
必须在两个列表上执行“相同”操作。您可能可以根据
t
类实际允许的方式玩相同的技巧。Two approaches come to mind:
Generate random types
Using GADTs, you could try to generate a "random type" and use that for testing your polymorphic function. This is not entirely easy, but it could be still feasible depending on your typeclass.
To give you a very rough sketch:
Testing non-integer types might come for free!
Every time we have a (terminating) polymorphic function, we know it satisfies a property called free theorem (the slogan is "theorems for free!"). E.g. if we have
f :: a->a
it has to be the identity, whileg :: a->a->a
has to be\x y->x
or\x y->y
. Adding a typeclass constraint like yourT a
makes it more complex, but a free theorem can still be generated.It is likely that, using such a free theorem, you can prove that if your property hold for integers it has to hold for any type in class
T
. I'll give you an example.Assume
f :: Ord a => [a] -> [a]
correctly sorts integers. Then, by the free theorem, it also sorts any other totally ordered type. Intuitively, this is becausef
can not really inspect the elements of the input list except using comparisons (<
,compare
,...). Hence, if you replace the list elements with suitable integers that have exactly the same comparison results,f
must perform the "same" operation on both lists.It is possible that you can play the same trick depending on what your
T
class actually allows.Typeclass带有一套法律,每个实施都应实现。每当添加新实施时,您都必须添加测试,以确保您的实现正确。
为了更容易编写这些测试,您可以使用库 https://hackage.haskage.haskage.org.org/package/ QuickCheck-classes 但是,最终,您将不得不编写一些代码,以测试针对实施的Typeclass定律。
The typeclass comes with a set of laws which should be fulfilled by each implementation. Whenever you add a new implementation you will have to add tests that make sure that your implementation is correct.
For writing those tests easier you may use libraries like https://hackage.haskell.org/package/quickcheck-classes but, eventually, you will have to write some code that tests the laws of typeclass against your implementation.