为什么我不能有一个“相等”的有理函数

问题描述 投票:0回答:1

我对 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 应该是有效的。

感谢您的帮助

function haskell equality haskell-platform
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
© www.soinside.com 2019 - 2024. All rights reserved.