(** Unify 2 types and, if exists, returns the substitution *)
let rec unify ty1 ty2 =
match ty1, ty2 with
| Type.Product (p1_ty1, p1_ty2), Type.Product (p2_ty1, p2_ty2)
| Type.Arrow (p1_ty1, p1_ty2), Type.Arrow (p2_ty1, p2_ty2) ->
(match unify p1_ty1 p2_ty1 with
| Some s1 ->
(match
unify (TypeSubstitution.apply s1 p1_ty2) (TypeSubstitution.apply s1 p2_ty2)
with
| Some s2 -> Some (TypeSubstitution.compose s2 s1)
| None -> None)
| ty1, ty2 when ty1 = ty2 -> Some TypeSubstitution.empty
| _ -> None
;;