我已经在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
但是我得到了这个错误:模式中的解析错误:(==)
答案 0 :(得分:4)
主要是将我已经写在评论中的内容更加充实地展示出来:
您的代码存在一些问题:
instance
声明下缩进代码。这样就告诉编译器什么代码属于实例声明。在以下行中,您要求在具体类型(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
实例来按顺序排列列表。
您可以以中缀或前缀形式定义(==)
,但不能同时定义两者。因此,(==) (Num (x,_)) (Num (y,_)) = x == y
或Num (x,_) == Num (y,_) = x == y
。
用于创建产品类型的Newtyping元组相当奇怪。如果要使用已存在的更复杂底层类型的功能,通常会使用Newtypes。但是,情况并非如此,您只需要Digits
和Sign
的正常产品。
您只是比较数字的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