Type class constraints on functions are turned into additional parameters. These additional parameters are used to pass type class dictionaries. For example the following type f :: (Num :a) (Ord :a) => :a -> :a -> :a would be compiled to the following lisp function definition.
(defun f (G103 G104 A-27 B-28)
...)Here G103 and G104 will hold the Num and Ord instance dictionaries for whichever :a is chosen by the caller. Variables with constraints are wrapped in a function.
Each class defines a struct with fields for methods and superclasses. For instance Num looks like:
(defstruct CLASS/NUM
SUPER-0 ; holds CLASS/EQ
+ ; remaining fields hold methods
-
*
FROMINT)Classes also define stub functions for dispatching methods on a dictionary. Each stub function selects the correct field from a dict and forwards the remaining arguments. See the definition of the + stub function below:
(defun + (dict a b)
(funcall (CLASS/NUM-+ dict) a b))Instances without constraints are compiled to variables.
(defvar |INSTANCE/NUM INTEGER|
(make-CLASS/NUM
:SUPER-0 |INSTANCE/EQ INTEGER|
:+ (lambda (a b)
(cl:+ a b))
:- (lambda (a b)
(cl:- a b))
:* (lambda (a b)
(cl:* a b))
:FROMINT (lambda (a)
a)))Instances with constraints such as such as Eq :a => (Eq (Optional :a)) are compiled to functions.
(defun |INSTANCE/EQ OPTIONAL :A| (G105)
(make-CLASS/NUM ...))Each method definion in an instance is also compiled to a seperate function. These functions are used for static method calls. The == method on Eq :a => (Eq (Optional :a)) would be compiled to:
(defun |INSTANCE/EQ OPTIONAL :A-=| (G106 a b)
...)Coalton maintains a mapping of (method, instance) -> static method. These mappings are used to rewrite method calls on instances known at compile time.
(+ |INSTANCE/NUM INTEGER| 1 2)becomes(|INSTANCE/NUM INTEGER-+| 1 2)(== (|INSTANCE/EQ OPTIONAL :A| G106) (Some a) (Some b))becomes(|INSTANCE/EQ OPTIONAL :A-==| G106 (Some a) (Some b))
Note that in the second example, the context variable G106 become a parameter to |INSTANCE/EQ OPTIONAL :A-==|.