0

Using Trees and defining a new "Eq" I'm getting an "Ambiguous class occurrence 'Eq' *** Could refer to: Hugs.Prelude.Eq Main.Eq".

I'm aware that I'm trying to add a new definition for the existing Eq-Class of the prelude, but I don't want to use import prelude hiding (Eq), because my new equality is using the "==" for numerical types. The Operator is called "=+", because it is not a real equality (which I think is already 'loaded' via deriving), but only a structural one.

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)

I'd be thankful for any suggestions.

StarsSky
  • 6,721
  • 6
  • 38
  • 63
  • 2
    Are you sure you need this at all? Why can't you simply use the derived `Eq` instance, which is basically equivalent to your custom one anyway (except for the missing cases `Nil =+ Node ...` which will crash your program if you keep them undefined). `==` is not "pointer identity" like in Java, in case you think so. – leftaroundabout Jan 18 '14 at 17:15

3 Answers3

3

If you want a new class to coexist with a predefined one, you should obviously give it a properly distinguishable name, e.g.

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

Simply qualifying the instance with Main.Eq does pretty much the same thing, but it's confusing to call your class Eq at all if it's "not real equality".

(Though == also doesn't need to be a proper equality; for many types this only means "equivalent in all regards the user can observe".)

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • Okay, using your hints I found a solution which does a real comparison of the tree's structure: [Can't post the code in a readable way] wich includes `Nil =+ Nil = True`, `Nil =+ (Node a tl tr) = False`,`(Node a tl tr) =+ Nil = False`,`(Node a tl1 tr1) =+ (Node b tl2 tr2) = (tl1=+tl2) && (tr1=+tr2)` I realized I made some mistakes within my first try. Nontheless my textbook says there should be a way of using an instance of Eq, meaning the solution of Zeta is asked for. I won't write it down ;o) – user3210273 Jan 18 '14 at 17:50
  • If the textbook says there should be an instance of `Eq` it either means the `derived` instance, or a custom one for `Prelude.Eq`; but almost certainly not a _new class_ also named `Eq`. "Overloading class names" is something only done in big projects that change the entire standard class hierarchies in some subtle way, like the [numeric prelude](http://hackage.haskell.org/package/numeric-prelude). – leftaroundabout Jan 18 '14 at 19:13
  • Hang on, actually even numeric-prelude doesn't do that... it uses its own, dramatically shortened names like `C` for a ring (roughly equivalent to `Num` numbers). – leftaroundabout Jan 18 '14 at 19:19
2

Just use fully qualified class names:

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)

But don't do that

You shouldn't create such ambiguity in first place. For example, your Eq should be called StructEq instead, if it's "only a structural one".

Zeta
  • 103,620
  • 13
  • 194
  • 236
0

Why are you deriving Eq if you want to write a custom one? Just drop Eq from the deriving clause, and this should all work.

MathematicalOrchid
  • 61,854
  • 19
  • 123
  • 220
  • Because I didn't want to implement a real equality, but a structural one. I posted a (for me) working code above. – user3210273 Jan 18 '14 at 17:55
  • Oh, I see. I hadn't noticed that the derived instance was actually used... it looked like you were just deriving an instance and then trying to write another one. – MathematicalOrchid Jan 18 '14 at 18:13