如何定义Category实例的相等性?

时间:2012-09-16 22:54:57

标签: haskell category-theory

为了证明例如类别法适用于数据类型的某些操作,如何确定如何定义相等?考虑以下类型来表示布尔表达式:

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

尝试证明 Exp 与身份 ETrue 和运营商形成一个类别是否可行:

(<&>) = EAnd

没有重新定义 Eq 实例?使用 Eq 的默认实例 left-identity 法则中断,即:

ETrue <&> e == e

评估为 False 。但是,定义 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

解决了这个问题。是否在(==)方面进行比较是声称满足此类法律的一般要求,还是足以说法律适用于特定类型的平等运算符?

1 个答案:

答案 0 :(得分:8)

平等为EVIL您很少(如果有的话)需要结构平等, 因为太强了。您只需要等效 足够强大 你在做什么。对于范畴理论尤其如此。

在Haskell中,deriving Eq将为您提供结构上的平等,这意味着您将会这样做 通常希望编写自己的== / /=实现。

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

旁注:如果使用该代码的某人认为您已定义了结构 等式测试,即用==检查是否有理由替换数据子组件 通过模式匹配,他们的代码可能会破坏。如果这很重要, 你可以隐藏构造函数以禁止模式匹配,或者可以定义你的 拥有class(例如,Equiv====/=)来区分这两个概念。 (这个 对于像Agda或Coq这样的定理证明来说,这对Haskell来说非常重要 难以获得实用/现实世界的代码,以致最终出现问题。)

真的很愚蠢(TM)的例子:让我们说那个人想打印一长串的巨大名单 Rat并认为记住Integer s的字符串表示将会保存 二进制到十进制转换。有Rat s的查找表,这样就相等了 Rat永远不会被转换两次,并且有一个整数查找表。如果 (a:/b) == (c:/d),将通过a - c /之间的复制来填充缺少的整数条目 b - d跳过转换(哎哟!)。对于列表[ 1:/1, 2:/2, 2:/4 ]1获取 转换然后,因为1:/1 == 2:/21的字符串被复制到。{1}} 2查询条目。最终结果是"1/1, 1/1, 1/4"