【发布时间】:2012-09-16 22:54:57
【问题描述】:
为了证明例如类别法则适用于对数据类型的某些操作,如何决定如何定义相等?考虑以下类型来表示布尔表达式:
data Exp
= ETrue
| EFalse
| EAnd Exp Exp
deriving (Eq)
试图证明 Exp 形成一个具有身份 ETrue 和运算符的类别是否可行:
(<&>) = EAnd
没有重新定义 Eq 实例?使用 Eq 的默认实例,left-identity 法则打破,即:
ETrue <&> e == e
评估为假。但是,定义一个 eval 函数:
eval ETrue = True
eval EFalse = False
eval (EAnd e1 e2) = eval e1 && eval e2
和 Eq 实例为:
instance Eq Exp where
e1 == e2 = eval e1 == eval e2
解决了这个问题。 (==) 方面的比较是声称满足此类定律的一般要求,还是说定律适用于特定类型的相等运算符就足够了?
【问题讨论】:
-
您没有义务使用
(==)的默认实现作为结构相等。如果您希望它表示与某些同构的等价,那很好。但是,如果可以通过其他方式轻松区分等价但不相同的值,那么这样做可能是不好的形式。这同样适用于类型类法律中的“平等”概念。 -
类别在哪里?只是好奇。
-
@n.m 我的印象是数学意义上的
Exp与箭头<&>和标识ETrue形成一个类别。但是,这与 Haskell 中的Category类型类不符,因为它需要更高种类的实例。对于这种数据类型,证明 Monoid 定律会是更好的选择。 -
嗯,它是一个幺半群,也是一个类别(每个幺半群都是一个类别),但是''不是一个箭头。 '' 是箭头组合。
Exps 是箭头。 -
作为使用非结构相等的类型示例,请参阅惰性字节串。