歧义出现 '=='

7

我正在学习Haskell,并试图弄清楚它的工作原理。

因此,我正在创建一个列表类,可以容纳混合的IntChar

data Algebra = Empty
|   Nmbr Int Algebra
|   Smbl Char Algebra

然后我尝试将其实例化为Eq的一个实例

instance Eq Algebra where
Empty == Empty              = True
(Nmbr x xl) == (Nmbr y yl)  = (x == y) && (xl==yl)
(Smbl x xl) == (Smbl y yl)  = (x == y) && (xl==yl)
_ == _                  = False

并且我遇到了一个“模糊的发生 ==”编译错误。它无法区分 Main.==Prelude.== 之间的区别。如果我手动替换所有 ==Main.== 或者 Prelude.== 那么就可以通过编译。
我不明白为什么编译器会有这么大的困难。在每种情况下,xy 明显被定义为 IntChar。我已经将我的操作与众多的教程示例(例如 http://www.haskell.org/tutorial/classes.html)进行了比较,但我无法确定为什么编译器在这种情况下会如此地讨厌 :P

另一个问题:deriving Eq 是否尝试做与我这里的代码完全相同的事情?我找不到关于 deriving 如何工作的好解释。 - Stephen Douglas Allen
是的,它确实支持。请参阅官方语言报告 - Ørjan Johansen
1个回答

10

你需要缩进你的instance定义中的内容:

instance Eq Algebra where
  Empty == Empty              = True
  (Nmbr x xl) == (Nmbr y yl)  = (x == y) && (xl==yl)
  (Smbl x xl) == (Smbl y yl)  = (x == y) && (xl==yl)
  _ == _                  = False
否则编译器将它视为两种不同的东西:
  • 一个具有空主体的instance Eq Algebra,会生成默认定义的 a == b = not (a /= b) 和相反的定义。

  • 一个新的中缀运算符==的定义。

因此,在您的代码中使用 == 现在会产生模糊性,即来自Prelude(在Eq中定义)和您的代码(Main)中的 ==之间的模糊性。

是的,deriving Eq 正好给出了这种结构上的等式。


哇!我发誓没有人解释过缩进是 Haskell 编程的必要部分。非常感谢! - Stephen Douglas Allen
2
@StephenDouglasAllen:在Haskell中,缩进是花括号和分号的语法糖。请查看Haskell报告以获取确切的定义:https://www.haskell.org/onlinereport/haskell2010/haskellch2.html#x7-210002.7。 - Jon Purdy
另一个问题:data语句需要缩进吗?我认为不需要,因为|符号将其保持在一起,对吗? - Stephen Douglas Allen
1
@StephenDouglasAllen 是的,它们是必需的。你给出的“data”定义对我来说无法编译。另外,顺便说一下,我建议使用空格而不是制表符(以防你正在使用制表符)。在Haskell中使用制表符肯定是可行的,但如果你不习惯那种风格,它可能会变得不太直观。 - David Young
4
在Haskell中使用制表符编程肯定是可行的,但在Haskell代码中使用制表符就像在C中使用所有单字母变量名一样:这不是必需的来赢得一个混淆的编程竞赛,但它肯定有帮助 - dfeuer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接