如何定义类的实例平等?(How to define equality for Category in

2019-07-31 15:08发布

为了证明例如类别的法律持有,用于对数据类型的一些操作,不要一个人如何决定如何界定平等? 考虑到以下类型代表布尔表达式:

data Exp
    = ETrue
    | EFalse
    | EAnd Exp Exp
    deriving (Eq)

是否可行试图证明精通形成以身份为ETrue和运营商类别:

(<&>) = EAnd

不需要重新定义实例? 利用公式的默认实例左身份法符,即:

ETrue <&> e == e

计算结果为 。 然而,定义eval函数

eval ETrue =  True
eval EFalse = False
eval (EAnd e1 e2) = eval e1 && eval e2

实例为:

instance Eq Exp where
    e1 == e2 = eval e1 == eval e2

解决了这个问题。 是比较在(==)总体要求的条款,声称为了满足这样的法律,或者是充分的理由认为法律持有特定类型相等运算符的?

Answer 1:

平等是邪恶的 。 你很少(如果有的话)需要结构性的平等 ,因为实在是太强了 。 您只需要一个等价那是你在做什么够强 。 这对范畴论尤其如此。

在Haskell中, deriving Eq会给你结构相等,这意味着你会经常需要编写自己的实现的== / /=

一个简单的例子:定义有理数作为对整数, data Rat = Integer :/ Integer 。 如果使用结构相等(什么Haskell是deriving ),你必须(1:/2) /= (2:/4)但作为一个分数1/2 == 2/4 。 你真正关心的是你的元组表示值,而不是他们的代表 。 这意味着您将需要一个比较分数降低一个等价 ,所以你应该实现来代替。

附注:如果有人使用代码假定您已经定义了一个结构平等的测试,即与检查==证明通过模式匹配替换数据子组件,它们的代码可能会断裂。 如果这是很重要的,你可以隐藏构造不允许模式匹配,或者可能定义自己的class (比方说, Equiv====/= )来分隔两个概念。 (这是定理证明像阿格达或勒柯克,在Haskell它真的很难得到实际/真实世界的代码错到最后东西坏了大部分重要的。)

真正愚蠢的(TM)例子:比方说,人要打印大量的长列表Rat S和认为memoizing的字符串表示Integer旨意节省二进制到十进制的转换。 有一个查找表Rat S,这样等于Rat旨意永远不会被转换两次,并有一个查找表的整数。 如果(a:/b) == (c:/d)丢失整数项,将被复制之间填充a - c / b - d跳过转换(!哎哟)。 对于列表[ 1:/1, 2:/2, 2:/4 ] 1被转换,然后,因为1:/1 == 2:/2 ,对于串1被复制到2查找条目。 最终的结果是"1/1, 1/1, 1/4"是borked。



文章来源: How to define equality for Category instances?