如何使用构造函数为数据类型正确实现实例 Eq?
How do I correctly implement an instance Eq for a data type with constructors?
我正在为 MyNum
数据类型实现 instance Eq
,数据类型为 分数 和 混合数字 构造函数(每个都有自己的参数)。
我也在使用 helper
函数将 MyNum
转换为 Rational
。这应该可以帮助我在 instance Eq
.
中进行比较时减少分数
问题是我在创建 instance Eq
时卡住了,我不确定是否还必须为 MyNum
数据类型定义一个新的 class Eq
。 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 = True
中的Fraction n d
和Fraction n d
都是模式,并且在左边的多个模式中使用相同的变量=
不允许登录。
您还需要将类型约束写为 (Eq n, Eq d) =>…
,而不是 Eq n d
,但这里没有区别,因为您不使用 type 参数,所以根本不需要 Eq
约束——你的 MyNum
类型使用的值的类型,它们都是 Integer
s,已经是 [= 的一个实例19=]:
instance Eq MyNum where
Fraction <b>n1</b> <b>d1</b> == Fraction <b>n2</b> <b>d2</b> | <b>n1 == n2 && d1 == d2</b> = True
-- …
Prolog,与unification一起工作,确实允许我们在头部多次使用同一个变量,以表示相等。
但是 Haskell 与 模式匹配 一起工作,因此不完全清楚重用同一个变量意味着什么,特别是因为不是每个类型都是Eq
.
您可能想利用您的 helper
函数将两个 MyNum
转换为 Rational
,以便您可以比较它们:
instance Eq MyNum where
x == y = helper x == helper y
你的typeMyNum
不带任何参数,所以你不能写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) = ...
我正在为 MyNum
数据类型实现 instance Eq
,数据类型为 分数 和 混合数字 构造函数(每个都有自己的参数)。
我也在使用 helper
函数将 MyNum
转换为 Rational
。这应该可以帮助我在 instance Eq
.
问题是我在创建 instance Eq
时卡住了,我不确定是否还必须为 MyNum
数据类型定义一个新的 class Eq
。 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 = True
中的Fraction n d
和Fraction n d
都是模式,并且在左边的多个模式中使用相同的变量=
不允许登录。
您还需要将类型约束写为 (Eq n, Eq d) =>…
,而不是 Eq n d
,但这里没有区别,因为您不使用 type 参数,所以根本不需要 Eq
约束——你的 MyNum
类型使用的值的类型,它们都是 Integer
s,已经是 [= 的一个实例19=]:
instance Eq MyNum where
Fraction <b>n1</b> <b>d1</b> == Fraction <b>n2</b> <b>d2</b> | <b>n1 == n2 && d1 == d2</b> = True
-- …
Prolog,与unification一起工作,确实允许我们在头部多次使用同一个变量,以表示相等。
但是 Haskell 与 模式匹配 一起工作,因此不完全清楚重用同一个变量意味着什么,特别是因为不是每个类型都是Eq
.
您可能想利用您的 helper
函数将两个 MyNum
转换为 Rational
,以便您可以比较它们:
instance Eq MyNum where
x == y = helper x == helper y
你的typeMyNum
不带任何参数,所以你不能写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) = ...