Next: , Previous: , Up: Type classes   [Contents]


10.6 Type class constraints on type class declarations

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.


Next: , Previous: , Up: Type classes   [Contents]