This document describes the transformation that the compiler does to implement type classes.

Tranformation of code using type classes

Every predicate which has a typeclass constraint is given an extra argument for every constraint in the predicate's type declaration. The argument is the "dictionary", or "typeclass_info" for the typeclass. The dictionary contains pointers to each of the class methods.

Representation of a typeclass_info: The typeclass_info is represented in two parts (the typeclass_info itself, and a base_typeclass_info), in a similar fashion to the type_info being represented in two parts (the type_info and the type_ctor_info).

The base_typeclass_info contains:

The typeclass_info contains:

The base_typeclass_info is produced statically, and there is one for each instance declaration. For each constraint on the instance declaration, the corresponding typeclass_info is stored in the second part.

eg. for the following program:

:- typeclass foo(T) where [...].
:- instance  foo(int) where [...].
:- instance  foo(list(T)) <= foo(T) where [...].
The typeclass_info for foo(int) is: The typeclass_info for foo(list(T)) is: If the "T" for the list is known, the whole typeclass_info will be static data. When we do not know until runtime, the typeclass_info is constructed dynamically.

Example of transformation

Take the following code as an example (assuming the declarations above), ignoring the requirement for super-homogeneous form for clarity:

:- pred p(T1) <= foo(T1).
:- pred q(T2, T3) <= foo(T2), bar(T3).
:- pred r(T4, T5) <= foo(T4).

p(X) :- q([X], 0), r(1, 0).
We add an extra argument for each type class constraint, and one argument for each unconstrained type variable.

:- pred p(typeclass_info(foo(T1)), T1).
:- pred q(typeclass_info(foo(T2)), typeclass_info(bar(T3)), T2, T3).
:- pred r(typeclass_info(foo(T4)), type_info(T5), T4, T5).
We transform the body of p to this:
p(TypeClassInfoT1, X) :-
	BaseTypeClassInfoT2 = base_typeclass_info(
		1,
		1,
		0,
		1,
		n5, (ie. the number of methods)
		...
		... (The methods for the foo class from the list
		...  instance)
		...
		),
	TypeClassInfoT2 = typeclass_info(
		BaseTypeClassInfoT2,
		TypeClassInfoT1,
		<type_info for list(T1)>),
	BaseTypeClassInfoT3 = base_typeclass_info(
		0,
		0,
		0,  (presuming bar has no superclasses)
		1,
		...
		... (The methods for the bar class from the int
		...  instance)
		...
		),
	TypeClassInfoT3 = typeclass_info(
		BaseTypeClassInfoT3,
		<type_info for int>),
	q(TypeClassInfoT2, TypeClassInfoT3, [X], 0),
	BaseTypeClassInfoT4 = baseclass_type_info(
		0,
		0,
		0,
		1,
		...
		... (The methods for the foo class from the int
		...  instance)
		...
		),
	TypeClassInfoT4 = typeclass_info(
		BaseTypeClassInfoT4,
		<type_info for int>),
	r(TypeClassInfoT4, <type_info for int>, X, 0).



Last update was $Date: 2000/05/10 18:09:38 $ by $Author: fjh $@cs.mu.oz.au.