Overview
The programmer defines a type class by specifying a set of function or constant names, together with their respective types, that must exist for every type that belongs to the class. In Haskell, types can be parameterized; a class Eq
intended to contain types that admit equality would be declared in the following way:
This declaration may be read as stating a "type a
belongs to class Eq
if there are functions named (==)
, and (/=)
, of the appropriate types, defined on it." (Note: Haskell's 'maps-to' operator, ->
, is 'right associative'. In other words, a -> a -> Bool
is read as a -> (a -> Bool)
.) A programmer could then define a function member
in the following way:
The function member
has the type a -> -> Bool
with the context (Eq a)
, which constrains the types which a
can range over to those a
which belong to the Eq
class. (Note: Haskell =>
can be called a 'class constraint'.)
A programmer can make any type t
a member of a given class C
by using an instance declaration that defines implementations of all of C
's methods for the particular type t
. For instance, if a programmer defines a new data type t
, they may then make this new type an instance of Eq
by providing an equality function over values of type t
in whatever way they see fit. Once they have done this, they may use the function member
on lists of elements of type t
.
Note that type classes are different from classes in object-oriented programming languages. In particular, Eq
is not a type: there is no such thing as a value of type Eq
.
Type classes are closely related to parametric polymorphism. For example, note that the type of member
as specified above would be the parametrically polymorphic type a -> -> Bool
were it not for the type class constraint "(Eq a) =>
".
Read more about this topic: Type Class