Хиндли-Милнер и унификация
От: dmz Россия  
Дата: 20.01.09 16:13
Оценка:
Разбираюсь тут по TAPL с Хиндли-Миллнером. Вроде бы осилил, но не вполне понятны некоторые аспекты, даже не в нем, а в процессе унификации.
Код из примера в TAPL (адаптированный и урезанный, что бы запускался):

(полный код — здесь)

let unify constr =
  let rec u constr = match constr with
      [] -> []
    | (tyS,TId(tyX)) :: rest ->
        if tyS = TId(tyX) then u rest
        else if occursin tyX tyS then raise Circular_constr
        else
          List.append (u (substinconstr tyX tyS rest)) 
                      [(TId(tyX),tyS)]
    | (TId(tyX),tyT) :: rest ->
        if tyT = TId(tyX) then u rest
        else if occursin tyX tyT then raise Circular_constr
        else
          List.append (u (substinconstr tyX tyT rest))
                      [(TId(tyX),tyT)]
    | (TInt,TInt) :: rest -> u rest
    | (TBool,TBool) :: rest -> u rest
    | (tyS,tyT)::rest -> raise Unsolvable
  in
    u constr

...
let s1 = [
        (TId("y"), TId("x")); 
        (TId("x"), TInt); 
        (TId("z"), TId("y")); 
]

let _ = 
    let    () = pconstr s1
    in let () = print_endline "solving..."
    in pconstr (unify s1)


результатом имеет:

y -> x
x -> TInt
z -> y
solving...
z -> TInt
y -> TInt
x -> y


ну то есть, x -> y не вывелось, хотя данных вроде как достаточно. Вопрос, собственно, вот в чем — это нормально вообще или нет? Баг или фича?


Т.е. если доработать алгоритм и зарядить его выход ему же на вход с проверкой, что количество решений увеличивается — то получаем вполне ожидаемый результат:

y -> x
x -> TInt
z -> y
solving...
z -> TInt
x -> TInt
y -> TInt


но, во-первых, не нравится то, что появилась функция проверки решений, и то, что вменяемые реализации на это решение не похожи (впрочем, там вообще нет двух похожих)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.