如何为自定义Rat类型创建Eq与Ord类型实例
为自定义Rat有理数类型实现Eq和Ord实例
你已经完成了有理数类型的规范化和显示逻辑,现在要让Rat成为Eq和Ord的实例,确保等价有理数(比如Rat 2 4和Rat 1 2)能正确判断相等,同时支持大小比较。
完整实现代码
gcd' :: Integer -> Integer -> Integer gcd' a b = if b == 0 then a else gcd' b (a `mod` b) data Rat = Rat Integer Integer normaliseRat :: Rat -> Rat normaliseRat (Rat num den) = let commonDivisor = gcd' (abs num) (abs den) num' = num `div` commonDivisor den' = den `div` commonDivisor in Rat (if den < 0 then (-num') else num') (abs den') createRat :: Integer -> Integer -> Rat createRat num den = normaliseRat (Rat num den) -- Show实例:格式化显示有理数 instance Show Rat where show (Rat num den) = show num ++ "/" ++ show den -- Eq实例:判断两个有理数是否相等 instance Eq Rat where r1 == r2 = let (Rat n1 d1) = normaliseRat r1 (Rat n2 d2) = normaliseRat r2 in n1 == n2 && d1 == d2 -- Ord实例:实现有理数的大小比较 instance Ord Rat where compare r1 r2 = let (Rat n1 d1) = normaliseRat r1 (Rat n2 d2) = normaliseRat r2 -- 交叉相乘比较,避免浮点数精度问题(分母均为正,不影响符号) left = n1 * d2 right = n2 * d1 in compare left right
关键说明
- Eq实例:不管输入的
Rat是否经过规范化,先通过normaliseRat统一转成标准形式,再直接比较分子和分母是否完全相等,这样就能保证Rat 2 4 == Rat 1 2返回True。 - Ord实例:利用有理数交叉相乘的性质(对于正数分母的有理数
a/b和c/d,a/b > c/d等价于a*d > c*b),避免使用浮点数转换带来的精度损失,同时确保比较逻辑的准确性。
测试示例
在GHCi中测试:
ghci> createRat 2 4 == createRat 1 2 True ghci> createRat 3 4 > createRat 1 2 True ghci> createRat (-1) 2 < createRat 1 3 True ghci> max (createRat 5 6) (createRat 3 4) 5/6
内容的提问来源于stack exchange,提问作者Anik kanti sikder
相关产品推荐
相关产品推荐

