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
.
Type class 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.