【问题标题】:Creating Instance of Eq for custom data type in Haskell在 Haskell 中为自定义数据类型创建 Eq 实例
【发布时间】:2017-04-03 08:43:45
【问题描述】:

我在 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

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

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

但我收到此错误:Parse error in pattern : (==)

【问题讨论】:

  • (==) (Num (x,_)) (Num (y,_)) = x==yNum (x,_) == Num (y,_) = x==y
  • 另外你为什么用newtype代替Numeral。为什么不data Numeral = Num Sign Digits
  • 当我输入你写的第一个案例时,它说模棱两可的出现 '==' 但在此之前它说它被多次声明(我猜在以前的例子中),而第二种情况不起作用好
  • 因为我想从书中解决问题
  • 您必须缩进实例功能的定义。在 Haskell 中,空格很重要。

标签: haskell typeclass instances custom-type


【解决方案1】:

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

您的代码存在一些问题:

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

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

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

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

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

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

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

  4. 使用新类型元组创建产品类型相当奇怪。如果您想使用已经为更复杂的底层类型提供的功能,通常会使用新类型。但是这里不是这样,您只需要DigitsSign 的普通产品。

  5. 您只是在比较数字中的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

【讨论】:

  • 解释得很好。我在教程的某个地方看到过,例如,使用 Eq a => Eq customType 的地方。我将其理解为包括将 Signs 与当前实例进行比较的实例。我知道我只比较了符号,我想为数字创建另一个 Eq 实例来比较数字。我想我已经尝试过你一开始写的,但没有奏效。现在我又试了一次,它说“模棱两可的发生==”。无论如何,解释得很好。
  • @PegasusThorn 谢谢。我在 2. 的末尾添加了一小段关于实例声明中的类型约束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 2013-11-25
相关资源
最近更新 更多