In fact, the syntax of Haskell takes a dual approach,
describing type classes in terms of predicates on types
(i.e., characteristic functions) rather than sets of types.
From a mathematical perspective, there is little to
distinguish between the two. However, predicates seem to
fit more comfortably into the language, and have a
The declaration at the top of this slide introduces the
Eq class by giving it a name, and by listing the operators
that it's elements (or "instances", as they are called) are
expected to support. The variable "a" used here represents
an arbitrary instance of the class, and serves as a placeholder
for the argument of the Eq predicate, and for the arguments of
the equality operator (==).
Instance declarations are required to populate a class.
For example, the two fragments shown here specify that Bool
is an equality type, and that lists are equality types if the
component values are themselves of an equality type.
(The actual definitions of equality in each case would be
written in place of the "..." shown here.) An important point
here is that the instance declarations for a class can be
distributed across the modules for a large program, and the
class can be extended at will to include new types are they
With these definitions in place, the Haskell type system
can determine which version of equality is required for any
given use of the (==) symbol. In the example shown here,
we are using the operator to compare lists of booleans, so
it is clear that we expect [Bool] to be an equality type
(i.e., that the predicate Eq [Bool] holds), which follows
directly by combining the two instance declarations on this