Précédent Remonter Suivant

3.6  Unification

La grande différence dans l'algorithme de typage du l-calcul et celui présenté ici provient de l'algorithme d'unification. dans le premier cas, la fonction TYPE retournait la liste des substitutions (l'unificateur principal UP) à appliquer pour que deux termes t1 et t2 vérifient UP(t1)=UP(t2). Cet algorithme bien que juste n'est pas forcément très efficace. En mini-ML, Les substitutions trouvées sont immédiatement appliquées aux types en effectuant une modification physique de ces types.

Deux problèmes se posent :

# let occurs n t = List.mem n (vars_of_type t);;
val occurs : int -> ml_type -> bool = <fun>
# let rec shorten = function
Var_type (vt) as tt ®
(match !vt with
Unknown _ ® tt
| Instanciated ((Var_type _) as t) ®
let t2 = shorten t in
vt := Instanciated t;
t2
| Instanciated t ® t
)
| t ® t;;
val shorten : ml_type -> ml_type = <fun>


La fonction unify_types prend deux types, modifie leur taille (par la fonction shorten) et les rend égaux ou échoue.


# let rec unify_types (t1,t2) =
let lt1 = shorten t1 and lt2 = shorten t2
in
match (lt1,lt2) with
| Var_type ( {contents=Unknown n} as occn ),
Var_type {contents=Unknown m} ®
if n=m then () else occn:= Instanciated lt2
| Var_type ({contents=(Unknown n)} as occn), _ ®
if occurs n lt2
then raise (Type_error(Clash(lt1,lt2)))
else occn:=Instanciated lt2
| _ , Var_type ({contents=(Unknown n)}) ® unify_types (lt2,lt1)
| Const_type ct1, Const_type ct2 ®
if ct1=ct2 then () else raise (Type_error(Clash(lt1,lt2)))
| Pair_type (t1,t2), Pair_type (t3,t4) ®
unify_types (t1,t3); unify_types(t2,t4)
| List_type t1, List_type t2 ® unify_types (t1,t2)
| Fun_type (t1,t2), Fun_type (t3,t4) ®
unify_types (t1,t3); unify_types(t2,t4)
| _ ® raise(Type_error(Clash(lt1,lt2)));;
val unify_types : ml_type * ml_type -> unit = <fun>



Précédent Remonter Suivant