为什么Eq类存在?

时间:2016-09-24 17:25:18

标签: haskell

假设我想定义模数为4的整数类型Mod4。毕竟,Int是Mod2^64。我可以采取的一个显而易见的方法是

data Mod4 = ZeroMod4 | OneMod4 | TwoMod4 | ThreeMod4 

但我也可以这样做

data Mod4 = Mod4 Integer

instance Eq Mod4 where
  (Mod4 x) == (Mod4 y) = (x-y) `mod` 4 == 0

但是这个功能有问题:

f :: Mod4 -> Mod4
f (Mod4 x) = if x < 20 then Mod4 0 else Mod4 1

f (Mod4 16)f (Mod4 20)不同,而这两个参数为==。所以我最终得到了两种平等:在记忆中的表现( Mod4 16Mod4 20)和==不同。

由于所有函数都可以模式匹配其参数,因此它们始终可以绕过任何==运算符。为什么Haskell没有将内存中的表示作为平等的定义?这样,所有类型都变得平凡。

实际上,功能的概念暗示了平等:在给定相等输入时产生相等输出的图形。因此,在一个不相等的类型上谈论函数是没有意义的。

1 个答案:

答案 0 :(得分:10)

  

为什么Haskell没有将内存中的表示作为相等的定义?这样,所有类型都变得平凡。

不。您无法比较Integer -> Bool类型的值。通常,无法比较函数。

回到黑板上。如何用类型化语言设计相等性?

一个选项是让(==) :: a -> a -> Bool,如果a是一个函数,则抛出异常。参见例如ocaml的。

另一种选择是在equatable / not equatable中分区类型。这是SML中的eqtype

另一个但相关的选择是将“eq-ability”表达为对多态性的约束。 Haskell中的Eq

现在,Eq可能更加特别。例如。您无法自己定义其实例,并且必须使用deriving Eq,类似于Typeable现在的工作方式。 而Haskell设计者则允许用户定义自己的比较函数。用户可能会知道一些“更聪明”的方式。例如。比较一个10场的记录,首先比较通常不同的字段,然后比较通常相等的字段,试图提高效率。

请注意,如果我们不导出数据类型构造函数,我们可以使等式成为等价并且仍然有用。例如。当Data.Set.Set表示同一个集合时,$( "#menu-button" ).click(function() { $("#right-sidebar").toggleClass("display"); if($("#right-sidebar").hasClass("display") == false){ $("#right-sidebar").css(opacity = "0"); } else { $("#right-sidebar").animate({ opacity: "1" }, "slow"); } }); 等同于不同的(平衡)树,但导出的接口永远不会破坏等价,所以相等看起来就像来自外部的相等。

  

因此,谈论一个不相等的类型的函数是没有意义的。

是的,当“不等于”在数学意义上解释时。然而。当它被解释为“等式谓词不可计算”时,它很有意义。我们可以谈论一个函数,它处理类型具有不可判定的相等性的值。