如何使用构造函数正确实现数据类型的实例 Eq?

问题描述

我正在为 instance Eq 数据类型实现一个 MyNum,它具有 FractionsMixed Numbers 作为数据构造函数(每个都有自己的参数).

我还使用 helper 函数将 MyNum 转换为 Rational。这应该有助于我在 instance Eq 中进行比较时减少分数。

问题是我在创建 instance Eq 时卡住了,我不确定是否还必须为 class Eq 数据类型定义新的 MyNumEq 的一般目的是比较使用辅助方法简化时两个分数是否相等。这是我目前所拥有的:

数据类型和构造函数:

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 dFraction 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)ndFraction 数据构造函数的参数,而不是类型。由于这些值是由助手处理的,我们也不需要在实例定义中关心它们。

请注意,要使上述实例起作用,helper 必须处理两种形式的数字,FractionMixed

helper:: MyNum -> Rational
helper (Fraction num denom)    = fromIntegral num / fromIntegral denom
helper (Mixed whole num denom) = ...

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...