Search code examples
haskellinstanceambiguous

Ambiguous occurrence '=='


I'm just learning Haskell and still trying to figure out how things work.

So I'm creating a list class that can hold a mixture of Int and Char.

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

Then I try to make it an instance of 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

and I get an Ambiguous occurrence == compile error. It can't tell the difference between Main.== and Prelude.==. If I manually replace all == with Main.== or Prelude.== then it compiles fine.

I don't see why the compiler is having so much difficulty here. x and y are clearly defined as being Int or Char in each case. I've compared what I am doing to the numerous tutorial examples (eg http://www.haskell.org/tutorial/classes.html) and I can't determine why the compiler is being such a jerk in this situation :P


Solution

  • You need to indent the body of your instance definition:

    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
    

    Otherwise the compiler sees it as two things:

    • An instance Eq Algebra with an empty body, producing the default definitions of a == b = not (a /= b) and vice versa.

    • A definition of a new infix operator named ==.

    Then using == in your code now produces an ambiguity between the == from Eq (defined in Prelude) and the == in your code (Main).

    And yes, deriving Eq gives you exactly this kind of structural equality.