【问题标题】:Ambiguous class occurence in HaskellHaskell中模棱两可的类出现
【发布时间】:2014-01-19 01:31:24
【问题描述】:

使用Trees 并定义一个新的“Eq”我得到一个"Ambiguous class occurrence 'Eq' *** Could refer to: Hugs.Prelude.Eq Main.Eq".

我知道我正在尝试为前奏的现有 Eq-Class 添加一个新定义,但我不想使用导入前奏隐藏 (Eq),因为我的新相等使用的是“ ==" 用于数字类型。运算符被称为“=+”,因为它不是一个真正的相等(我认为它已经通过派生“加载”了),而只是一个结构相等。

data Tree = Nil | Node Int Tree Tree deriving (Eq, Ord, Show)
instance Eq Tree where
    Nil =+ Nil      =  true
    (Node a tl1 tr1) =+ (Node b tl2 tr2) = (a==b) && (tl1==tl2) && (tl1==tl2)

如果有任何建议,我将不胜感激。

【问题讨论】:

  • 你确定你需要这个吗?为什么你不能简单地使用派生的Eq 实例,它基本上等同于你的自定义实例(除了缺少的情况Nil =+ Node ...,如果你保持它们未定义,它将使你的程序崩溃)。 == 不是 Java 中的“指针标识”,以防万一。

标签: class haskell ambiguous


【解决方案1】:

如果您希望新类与预定义的类共存,您显然应该给它一个适当可区分的名称,例如

class PseudoEq x where
  (=+) :: x -> x -> Bool

instance PseudoEq Tree where
    Nil            =+ Nil            =  true
    Node a tl1 tr1 =+ Node b tl2 tr2 
          = a==b && tl1==tl2 && tl1==tl2

简单地用Main.Eq 限定实例几乎可以做同样的事情,但是如果它“不是真正的平等”,那么将你的类称为Eq 会令人困惑。

(虽然== 也不需要是适当的相等;对于许多类型,这仅意味着“在用户可以观察到的所有方面都相等”。)

【讨论】:

  • 好的,根据您的提示,我找到了一个对树结构进行真正比较的解决方案:[无法以可读的方式发布代码] 其中包括 Nil =+ Nil = TrueNil =+ (Node a tl tr) = False、@ 987654328@,(Node a tl1 tr1) =+ (Node b tl2 tr2) = (tl1=+tl2) && (tr1=+tr2) 我意识到我在第一次尝试时犯了一些错误。尽管如此,我的教科书说应该有一种使用 Eq 实例的方法,这意味着需要 Zeta 的解决方案。我不会写下来;o)
  • 如果教科书上说应该有Eq 的实例,它要么表示derived 实例,要么是Prelude.Eq 的自定义实例;但几乎可以肯定不是一个新类也叫Eq。 “重载类名”仅在以某种微妙方式改变整个标准类层次结构的大型项目中进行,例如numeric prelude
  • 等一下,实际上即使是 numeric-prelude 也不会这样做...它使用自己的、显着缩短的名称,例如 C 用于环(大致相当于 Num 数字)。
【解决方案2】:

只需使用完全限定的类名:

module Main where

data Tree = Nil | Node Int Tree Tree deriving (Prelude.Eq, Ord, Show)

class Eq a where
  (=+) :: a -> a -> Bool

instance Main.Eq Tree where
    Nil =+ Nil      =  True
    (Node a tl1 tr1) =+ (Node b tl2 tr2) = (a==b) && (tl1==tl2) && (tl1==tl2)

但不要那样做

你不应该首先制造这种模棱两可的东西。例如,您的Eq 应该改为StructEq,如果它是“只是一个结构性的”

【讨论】:

    【解决方案3】:

    如果你想写一个自定义的,你为什么要派生Eq?只需从派生子句中删除Eq,这一切都应该有效。

    【讨论】:

    • 因为我不想实现真正的平等,而是结构平等。我在上面发布了一个(对我来说)工作代码。
    • 哦,我明白了。我没有注意到实际上使用了派生实例......看起来你只是在派生一个实例,然后尝试编写另一个实例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 2012-12-18
    • 2014-08-12
    • 2012-10-18
    • 2018-10-25
    相关资源
    最近更新 更多