我对 haskell 很陌生,有一个关于 Eq 的问题。
data Rat = Rat Integer Integer
normaliseRat :: Rat -> Rat
normaliseRat (Rat x y)
|x < 0 && y < 0 = Rat (-x) (-y)
|otherwise = Rat (x `div`(gcd x y)) (y `div` (gcd x y))
所以我有一个 func normaliseRat。我需要的是 Eq 和 Ord 的实例。当然,Rat 2 4 == Rat 1 2 应该是有效的。
感谢您的帮助
Haskell 不支持 function 重载。但
(==)
不是一个函数;而是一个函数。它被声明为类型类方法,因此该方法的任何特定于类型的实现都必须在 instance
声明中定义,如下所示:
instance Eq Rat where
(Rat x y) == (Rat n m) = x * m == y * n
(交叉相乘后,
x/y == n/m
相当于x * m == y * n
;乘法效率更高,并且不会出现除法带来的精度问题。)
这同样适用于
Ord
,只不过您可以选择实施 (<=)
或 compare
。 (考虑到其中任何一个,其他比较方法的默认定义都将起作用。)
instance Ord Rat where
-- I leave fixing this to accommodate negative numbers
-- correctly as an exercise.
(Rat x y) <= (Rat n m) = (x * m) <= (y * n)
作为类型类方法,
(==)
实际上是一个完整的函数系列,按其所使用的类型进行索引。 instance
声明的目的不是重新定义方法,而是向该系列添加一个新函数。
如果启用
TypeApplications
扩展,您可以将 (==)
视为从类型到函数的映射。
> :t (==)
(==) :: Eq a => a -> a -> Bool
> :t (==) @Int
(==) @Int :: Int -> Int -> Bool
无需类型应用程序,Haskell 的类型检查器会自动找出要使用的函数:
> (==) 'c' 'd'
False
> (==) 3 5
False
但你可以明确表示:
> (==) @Char 'c 'd'
False
> (==) @Char 3 5
<interactive>:9:12: error:
• No instance for (Num Char) arising from the literal ‘3’
• In the second argument of ‘(==)’, namely ‘3’
In the expression: (==) @Char 3 5
In an equation for ‘it’: it = (==) @Char 3 5