Next: Type class constraints on instance declarations, Previous: Type class constraints on predicates and functions, Up: Type classes [Contents]

Type class constraints may also appear in `typeclass`

declarations,
meaning that one type class is a “superclass” of another.

The arguments of a constraint on a type class declaration must be either type variables or ground types. Each constraint must contain at least one variable argument and all variables that appear in the arguments must also be arguments to the type class in question.

For example, the following declares the ‘`ring`’ type class, which describes
types with a particular set of numerical operations defined:

:- typeclass ring(T) where [ func zero = (T::out) is det, % '+' identity func one = (T::out) is det, % '*' identity func plus(T::in, T::in) = (T::out) is det, % '+'/2 (forward mode) func mult(T::in, T::in) = (T::out) is det, % '*'/2 (forward mode) func negative(T::in) = (T::out) is det % '-'/1 (forward mode) ].

We can now add the following declaration:

:- typeclass euclidean(T) <= ring(T) where [ func div(T::in, T::in) = (T::out) is det, func mod(T::in, T::in) = (T::out) is det ].

This introduces a new type class, `euclidean`

, of which `ring`

is a
superclass. The operations defined by the `euclidean`

type class are
`div`

, `mod`

, as well as all those defined by the `ring`

type class. Any type declared to be an instance of `euclidean`

must also
be declared to be an instance of `ring`

.

Typeclass constraints on type class declarations gives rise to a superclass relation. This relation must be acyclic. That is, it is an error if a type class is its own (direct or indirect) superclass.