问题描述
我正在为 instance Eq
数据类型实现一个 MyNum
,它具有 Fractions 和 Mixed Numbers 作为数据构造函数(每个都有自己的参数).
我还使用 helper
函数将 MyNum
转换为 Rational
。这应该有助于我在 instance Eq
中进行比较时减少分数。
问题是我在创建 instance Eq
时卡住了,我不确定是否还必须为 class Eq
数据类型定义新的 MyNum
。 Eq
的一般目的是比较使用辅助方法简化时两个分数是否相等。这是我目前所拥有的:
数据类型和构造函数:
data MyNum = Fraction {num :: Integer,denom :: Integer}
| Mixed {whole :: Integer,num:: Integer,denom :: Integer}
助手:
helper :: MyNum -> Rational
helper (Fraction num denom) = (fromIntegral num ) / (fromIntegral denom)
当前Eq
:
instance (Eq n d) => Eq (MyNum n d) where
Fraction n d == Fraction n d = True
-- Mixed _ _ _ == Mixed _ _ _ = True
上面的 Eq
代码抛出以下错误:
MyNum.hs:29:16: error:
* Conflicting definitions for `d'
Bound at: MyNum.hs:29:16
MyNum.hs:29:32
* In an equation for `=='
|
29 | Fraction n d == Fraction n d = True
| ^^^^^^^^^^^^^^^^^
解决方法
发生这种情况的原因是您在 n
方法定义的头部使用了两次 d
和 ==
,这是不允许的。
Fraction n d
中的 Fraction n d
和 Fraction n d == Fraction n d = True
都是模式,并且在 {{1} 左侧的多个模式中使用相同的变量} 不允许登录。
您还需要将类型约束写为 =
,而不是 (Eq n,Eq d) =>…
,但这里没有区别,因为您无论如何都不使用 type 参数,所以根本不需要 Eq n d
约束——您的 Eq
类型使用的值的类型,都是 MyNum
,已经是 Integer
的实例:
Eq
与统一一起使用的 Prolog 确实允许我们在头部多次使用相同的变量,以表示相等。
但是 Haskell 使用模式匹配,因此并不完全清楚重用相同变量意味着什么,特别是因为并非每个类型都是 instance Eq MyNum where
Fraction n1 d1 == Fraction n2 d2 | n1 == n2 && d1 == d2 = True
-- …
的实例。
您可能希望利用 helper
函数将两个 MyNum
转换为 Rational
,以便您可以比较它们:
instance Eq MyNum where
x == y = helper x == helper y
你的类型 MyNum
不带任何参数,所以你不能写 Eq (MyNum n d)
。 n
和 d
是 值,Fraction
数据构造函数的参数,而不是类型。由于这些值是由助手处理的,我们也不需要在实例定义中关心它们。
请注意,要使上述实例起作用,helper
必须处理两种形式的数字,Fraction
和 Mixed
。
helper:: MyNum -> Rational
helper (Fraction num denom) = fromIntegral num / fromIntegral denom
helper (Mixed whole num denom) = ...