Haskell中Eq、Ord类自定义实例实现及比较方法咨询
自定义数据类型的Eq与Ord实例实现讲解
先从Eq类说起
Eq类用于定义相等性判断,核心是实现==运算符(/=有默认实现,基于==,通常无需手动编写)。
方式1:自动派生
如果你的数据类型的相等逻辑是按字段顺序逐一比较,直接在定义时加deriving (Eq)即可,Haskell会自动生成实例:
-- 定义包含姓名和年龄的Person类型 data Person = Person String Int deriving (Eq) -- 使用示例:只要姓名和年龄都匹配,就判定相等 testEq1 :: Bool testEq1 = Person "Alice" 25 == Person "Alice" 25 -- 结果为True testEq2 :: Bool testEq2 = Person "Alice" 25 == Person "Bob" 25 -- 结果为False
方式2:手动实现自定义相等逻辑
如果需要忽略某些字段(比如只比较年龄,不管姓名),就手动编写instance Eq:
data Person = Person String Int instance Eq Person where -- 只比较年龄字段,忽略姓名 (Person _ age1) == (Person _ age2) = age1 == age2 -- 使用示例:姓名不同但年龄相同,判定相等 testEq3 :: Bool testEq3 = Person "Alice" 25 == Person "Bob" 25 -- 结果为True
再讲Ord类
Ord类用于定义排序逻辑,它继承自Eq,所以必须先有Eq实例(自动或手动实现均可)。核心是实现compare函数(返回LT/EQ/GT,其他比较运算符</<=/>/>=、max/min都有默认实现,基于compare)。
方式1:自动派生
如果排序逻辑是按字段顺序优先级比较(先比第一个字段,相等再比第二个,以此类推),加deriving (Ord)即可:
data Person = Person String Int deriving (Eq, Ord) -- 使用示例:先比较姓名的字典序,姓名相同再比年龄 testOrd1 :: Bool testOrd1 = Person "Alice" 30 < Person "Bob" 20 -- 结果为True("Alice"字典序早于"Bob") testOrd2 :: Bool testOrd2 = Person "Alice" 20 < Person "Alice" 30 -- 结果为True
方式2:手动实现自定义排序逻辑
如果要改变排序优先级(比如先比年龄,年龄相同再比姓名),手动编写instance Ord:
data Person = Person String Int deriving (Eq) instance Ord Person where compare (Person name1 age1) (Person name2 age2) = -- 先比较年龄,年龄相等再比较姓名 case compare age1 age2 of EQ -> compare name1 name2 other -> other -- 使用示例:年龄小的排前面,年龄相同再看姓名 testOrd3 :: Bool testOrd3 = Person "Bob" 20 < Person "Alice" 25 -- 结果为True(20 < 25) testOrd4 :: Bool testOrd4 = Person "Bob" 25 < Person "Alice" 25 -- 结果为False("Bob"字典序晚于"Alice")
枚举类型的自定义Ord示例
如果是枚举类型,自动派生的Ord顺序就是定义时的顺序,手动实现可以修改这个顺序:
data Color = Red | Green | Blue deriving (Eq) -- 自定义排序:Green < Red < Blue instance Ord Color where compare Green _ = LT compare _ Green = GT compare Red Blue = LT compare Blue Red = GT compare _ _ = EQ testOrd5 :: Bool testOrd5 = Green < Red -- 结果为True testOrd6 :: Bool testOrd6 = Red < Blue -- 结果为True
注意事项
手动实现时必须遵守类的定律:
- Eq:自反性(
x == x永远为True)、对称性(x == y则y == x)、传递性(x == y且y == z则x == z) - Ord:全序性(任意两个值的比较结果必须是LT/EQ/GT中的一个,且满足传递性等规则)
内容的提问来源于stack exchange,提问作者user20556271
相关产品推荐
相关产品推荐

