在 Haskell 中为自定义数据类型创建 Eq 实例

Creating Instance of Eq for custom data type in Haskell

我已经为 Haskell 中的数字表示创建了一些自定义数据类型,现在我想为它实现 Eq 实例,但我不知何故卡住了。所以我已经做了:

data Digit = Zero | One | Two
type Digits = [Digit]
data Sign = Pos | Neg -- Pos fuer Positive, Neg fuer Negative
newtype Numeral = Num (Sign,Digits)

instance Eq Sign where
(==) Pos Pos = True
(==) Neg Neg = True
(==) _ _ = False

instance Eq Digit where
(==) Zero Zero = True
(==) One One = True
(==) Two Two = True
(==) _ _ = False

现在我想检查自定义类型数字中的登录,所以我尝试了这个:

instance (Eq Sign) => Eq (Numeral) where
(==) Num(x,_)== Num(y,_) = x==y

但我收到此错误:模式解析错误:(==)

主要是将我已经写在评论中的内容以更充实的形式呈现:

您的代码存在一些问题:

  1. 您必须缩进 instance 声明下的代码。这样你就可以告诉编译器哪些代码属于实例声明。
  2. 在下一行中,您要求对具体类型 (Eq Sign =>) 进行类型 class 约束。这在标准 Haskell 中是不可能的,即使您遵循编译器说明并启用 FlexibleInstances 语言扩展也没有意义。

    instance (Eq Sign) => Eq (Numeral) where
    

    类型 class 约束仅用于类型变量。例如:

    double :: Num a => a -> a
    double x = x + x
    

    这里我们说,函数 double 仅适用于实现 Num 的所有类型。 double :: Num Int => Int -> Int 另一方面是多余的,因为我们已经知道 Int 有一个 Num 实例。 Eq Sign.

    也一样

    对于实例,只有当您为其编写实例的类型包含另一个多态类型时,此类约束才有意义。福克斯例子instance Ord a => Ord [a]。这里我们将使用列表元素的 Ord 实例来按字典顺序排列列表。

  3. 您可以用中缀或前缀形式定义 (==),但不能同时使用这两种形式。所以 (==) (Num (x,_)) (Num (y,_)) = x == yNum (x,_) == Num (y,_) = x == y.

  4. 用新类型的元组来创建产品类型是相当奇怪的。如果您想使用更复杂的基础类型已经存在的功能,通常会使用新类型。但是这里不是这种情况,您只需要 DigitsSign.

  5. 的正常乘积
  6. 您只是在比较 Sign 个数字。虽然从技术上讲是一个有效的 Eq 实例,但我认为您还想比较可能截断前导零的数字的数字。在下面的代码中,为了简单起见,我没有截断零。

data Digit = Zero | One | Two
type Digits = [Digit]
data Sign = Pos | Neg
data Numeral = Num Sign Digits

instance Eq Sign where
  (==) Pos Pos = True
  (==) Neg Neg = True
  (==) _ _ = False

instance Eq Digit where
  (==) Zero Zero = True
  (==) One One = True
  (==) Two Two = True
  (==) _ _ = False

instance Eq Numeral where
  Num s1 x1 == Num s2 x2 = s1 == s2 && x1 == x2