Précédent Index Suivant

1.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 Index Suivant