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

Why cant i have a "equal" rational function

提问人:newcodder 提问时间:11/15/2022 最后编辑:M. Justinnewcodder 更新时间:11/7/2023 访问量:130

问:

我对 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 的实例。当然,老鼠 2 4 == 老鼠 1 2 应该是有效的。

感谢您的帮助

函数 haskell 等式 haskell-platform

评论

0赞 newcodder 11/15/2022
忘了写 Rat (x y) == Rat (n m) = (x/y) == (n/m) 这就是我尝试制作 eq :( 的方式正如你所建议的那样,这是错误的
0赞 Noughtmare 11/15/2022
您可以编辑您的问题。但除此之外,问题还有什么?你试过写实例吗?
2赞 chepner 11/15/2022
是什么阻止了你写作?instance Eq Rat where (Rat x1 y1) == (Rat x2 y2) = ...instance Ord Rat where compare (Rat x1 y1) (Rat x2 y2) = ...
0赞 newcodder 11/15/2022
@Noughtmare是的,我是这样写的: 实例 Eq Rat 其中
3赞 Daniel Wagner 11/15/2022
normalizeRat (Rat (-4) (-2))似乎它可能给出了错误的答案,具有明显的规格。normalizeRat

答:

2赞 chepner 11/15/2022 #1

Haskell 不支持函数重载。但不是函数;它被声明为 TypeClass 方法,因此必须在声明中定义该方法的任何特定于类型的实现,如下所示:(==)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

评论

0赞 newcodder 11/15/2022
当我写你在那里写的东西时,我得到了一个错误。x * m == y *n 我得到“==”一个错误,说这是一个模棱两可的情况
0赞 newcodder 11/15/2022
啊,好吧。因此,当我编写代码时,它应该看起来像这样: (==) (Rat x y) (Rat m n) = xm == yn ??
1赞 chepner 11/15/2022
你不应该需要。我无法重现您声称看到的错误。
1赞 chepner 11/15/2022
您确定您完全按照所示键入了它吗?确切的错误消息是什么?
1赞 Daniel Wagner 11/16/2022
您的定义需要谨慎。如果有理数没有被归一化,也许其中一个分母是负数(而不是另一个分母)——那么 必须变成 !Ord<=>=