(** 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) | None -> None) | ty1, ty2 when ty1 = ty2 -> Some TypeSubstitution.empty | _ -> None ;;