Я пишу функцию в OCaml, чтобы проверить, являются ли два типа унифицируемыми, и создаст объединитель, если таковой имеется, или напечатает соответствующее сообщение.
Вот система типов:
type typExp =
| TypInt
| TypVar of char
| Arrow of typExp * typExp
| Lst of typExp;;
type substitution = (char * typExp) list;;
Я написал метод для выполнения замены переменной выражением типа с учетом правил подстановки замены типа.
let rec substitute (tau1 : typExp) (v : char) (tau2 : typExp) : typExp =
match tau2 with
|TypInt -> TypInt
|TypVar q -> (if(q=v) then tau1 else TypVar q)
|Arrow (q,w) -> Arrow ((substitute tau1 v q), (substitute tau1 v w))
|Lst q -> Lst (substitute tau1 v q)
;;
let rec applySubst (sigma: substitution) (tau: typExp) : typExp =
let reversedList = List.rev sigma in
match reversedList with
|(a,s)::w -> applySubst (List.rev w) (substitute s a tau)
|[]->tau
;;
Я использовал эти методы для реализации функции проверки unifiable, однако, когда два типа не являются unifiable, он должен напечатать сообщение на экране, а метод print возвращает тип единицы, а не тип замены. Я не знаю, как с этим справиться.
let unify (tau1: typExp) (tau2:typExp) : substitution =
let rec helper acc t1 t2=
match t1, t2 with
| TypInt,TypInt -> acc(*not the problem*)
| TypInt, TypVar q -> (q,TypInt)::acc
| TypInt, Arrow (a,b) -> print_string "Not Unifyable" (* aproblem here*)
| TypInt, Lst a -> print_string "Not Unifyable"
| TypVar q, TypInt -> (q, TypInt)::acc
| TypVar q, Arrow (a,s) -> (q,Arrow(a,s))::acc
| TypVar q, Lst w -> (q, Lst w)::acc
| TypVar a, TypVar b ->( if(a=b) then acc else (a,TypVar b)::acc)
| Arrow(q,w), Arrow(a,s) -> if (helper [] w s)=[] then []
else helper (helper [] w s) (applySubst (helper [] w s) q) (applySubst (helper [] w s) a)
| Arrow (q,w), TypInt -> print_string "Not Unifyable"
| Arrow (q,w), TypVar a -> (a, Arrow(q,w))::acc
| Arrow (q,w), Lst a -> []
| Lst q, TypInt -> []
| Lst q, TypVar a -> (a,Lst q)::acc
| Lst q, Arrow (s,t) -> []
| Lst q, Lst w -> helper acc q w
in helper [] tau1 tau2
Мне интересно, не используя тип параметра, есть ли другой способ справиться с этим?