为了证明例如类别的法律持有,用于对数据类型的一些操作,不要一个人如何决定如何界定平等? 考虑到以下类型代表布尔表达式:
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
解决了这个问题。 是比较在(==)总体要求的条款,声称为了满足这样的法律,或者是充分的理由认为法律持有特定类型相等运算符的?
平等是邪恶的 。 你很少(如果有的话)需要结构性的平等 ,因为实在是太强了 。 您只需要一个等价那是你在做什么够强 。 这对范畴论尤其如此。
在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。