Reputation: 17248
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??
Upvotes: 3
Views: 1450
Reputation: 8276
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.
Upvotes: 0
Reputation: 62818
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
".
Upvotes: 9
Reputation: 234484
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]
).
Upvotes: 4
Reputation: 129764
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.
Upvotes: 2