3

I am currently reading this, but if I am honest I am struggling to see what

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

achieves, which

instance Eq Integer where 
  x == y                =  x `integerEq` y

doesnt achieve. I understand the second code defines what the result of performing equality on two Integer types should be. What is the purpose of the first then??

Matt Fenwick
  • 48,199
  • 22
  • 128
  • 192
intrigued_66
  • 16,082
  • 51
  • 118
  • 189
  • 8
    One is a type class, the other is a type instance. The former describes what the types of that type class can do (interface), the latter describes how it's done (implementation). (Disclaimer: I really don't know Haskell. This is a wild guess from the syntax and what little I read about it.) – Xeo Sep 21 '12 at 11:22
  • 1
    @Xeo you are right. One could interpret that Haskell's typeclass matches java's interface. Haskell's instance matches Java's interface implementation. – Simon Bergot Sep 21 '12 at 12:07
  • 3
    @Philipp Haskell type classes have nothing to do with oop. – Matvey Aksenov Sep 21 '12 at 12:14

4 Answers4

9

The class declaration says "I'm going to define a bunch of functions now which will work for several different types". The instance declaration says "this is how these functions work for this type".

In your specific example, class Eq says that "Eq means any type that has a function named ==", whereas the instance Eq Integer says "this is how == works for an Integer".

MathematicalOrchid
  • 61,854
  • 19
  • 123
  • 220
4

The first defines what operations must be provided for a type to be comparable for equality. You can then use that to write functions that operate on any type that is comparable for equality, not just integers.

allSame :: Eq a => [a] -> Bool
allSame [] = []
allSame (x:xs) = foldr True (==x) xs

This function works for integers because instances for Eq Integer exists. It also works for strings ([Char]) because an instance for Eq Char exists, and an instance for lists of types that have instances of Eq also exists (instance Eq a => Eq [a]).

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • So the first is like an OO interface? Are the two related? Is it possible to use classes without instances and vice versa? – intrigued_66 Sep 21 '12 at 11:26
  • There are some similarities, but they're not at all the same. You can write functions that use classes without having any instance defined. But you cannot call those functions without a type that has an instance of that class. The example in my post doesn't need any instance to exist, but calling the function needs. In any case, I don't think it's good to think of it in terms of OOP. – R. Martinho Fernandes Sep 21 '12 at 11:31
  • So the Eq a says "I (or Prelude) have already defined equality functions for the type- a? So this means the compiler can statically allow it to compile (emphasis- that you may not have defined them and receive a run-time error??) – intrigued_66 Sep 21 '12 at 11:39
  • No, `Eq a` means "whoever calls this function may do so with any type `a`, as long as that type `a` implements the `Eq` typeclass." Any attempt to call the function with a type that does not implement that typeclass will result in a *compile-time* error. – dave4420 Sep 21 '12 at 12:16
  • 5
    @mezamorphic: They're not really related, but as far as fundamentally wrong analogies for type classes go, "like an OO interface" is the least wrong I know of. Type classes are in general more powerful than interfaces, but in many ways they serve similar purposes. – C. A. McCann Sep 21 '12 at 13:11
  • @mezamorphic: type classes are like OO interfaces in one specific way. An interface defines a set of functions that can be used with any type that implements that interface. A type class defines a set of functions that can be used with any type that is an instance of that class. In this much they're similar. This falls apart with rigorous definitions because OO interfaces usually imply stuff that isn't included with Haskell type classes and vice-versa. Thinking of them as equivalent leads to problems when you try to use type classes like OO interfaces. – John L Sep 24 '12 at 03:54
  • I feel obligated to mention that even my above description of type classes is limited to a specific subset of type classes. That's another problem with the type class/interface comparison: it doesn't really help with understanding a lot of the more interesting uses of type classes. – John L Sep 24 '12 at 03:58
2

There is one class and many instances for different types. That's why the class specifies the required signature (interface; classes can also specify default implementations, but that's beside the point), and instance the body (implementation). You then use class name as a constraint that means "any type a that implements Eq operations, i.e. have an instance in Eq".

Read Learn you a Haskell or Real World Haskell, they're better than the haskell.org tutorial.

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
0

Let's say you want to implement a generic algorithm or data structure, "generic" meaning polymorphic: it should work for any data type. For example, let's say you want to write a function that determines whether three input values are equal.

Taking a specific (monomorphic) case, you can do this for integers:

eq3 :: Int -> Int -> Int -> Bool
eq3 x y z = x == y && y == z

We'd expect the above definition to work for other types as well, of course, but if we simply tell the compiler that the function should apply to any type:

eq3 :: a -> a -> a -> Bool
eq3 x y z = x == y && y == z

... the compiler complains that the == function doesn't apply to our generic a:

<interactive>:12:49:
    No instance for (Eq a)
      arising from a use of `=='
    In the first argument of `(&&)', namely `x == y'
    In the expression: x == y && y == z
    In an equation for `eq3': eq3 x y z = x == y && y == z

We have to tell the compiler that our type a is an instance of the Eq type class, which you already noticed is where the == function is declared. See the difference here:

eq3 :: Eq a => a -> a -> a -> Bool
eq3 x y z = x == y && y == z

Now we have a function that can operate uniformly on any type a belonging to the Eq type class.

mergeconflict
  • 8,156
  • 34
  • 63