У меня возникли проблемы с пониманием letrec определение системы HM, которая дается в Википедии, здесь: https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Recursive_definitionsПравильная форма letrec в системе типа Hindley-Milner?
Для меня, это правило переводит примерно к следующему алгоритму:
- типов Infer на все в Частей
letrec
определения- присвоить переменные временные типа для каждого определенного идентификатора
- рекурсивно обрабатывать все определения типов с временными
- в парах, объединить результаты с первоначальными временных переменных
- близко (с
forall
) выведенный типы, добавить их к базису (контекст) и вывод типов выражения части с ним
У меня возникли проблемы с программой, как это:
letrec
p = (+) --has type Uint -> Uint -> Uint
x = (letrec
test = p 5 5
in test)
in x
поведение Я наблюдение выглядит следующим образом:
- определение
p
получает типа ВРЕМЕННУЮa
- определения
x
получает некоторый временный типа тоже, но это из нашей области в настоящее время - в
x
, определениеtest
получает временный видt
p
Получает временный типa
из области применения, используя правило HM для переменной(f 5)
обрабатывается по правилу HM для приложения, в результате получается типb
(и объединение, что (a
объединяет сUint -> b
)((p 5) 5)
, обрабатывается по тому же правилу, что приводит к более унификации и типаc
,a
в настоящее время в результате унифицируется сUint -> Uint -> c
- теперь, тест закрывается к типу
forall c.c
- переменный тест
in test
получает экземпляр типа (илиforall c.c
) с новыми переменными, accrodingly правилу HM для переменного, в результате чегоtest :: d
(который объединен сtest::t
прямо на) - в результате
x
эффективно типаd
(илиt
, в зависимости от настроения объединения)
Проблемы: x
, очевидно, должен иметь тип Uint
, но я не вижу, как эти два могли объединить для получения типа. Существует потеря информации, когда тип test
закрывается, и экземпляр снова повторяет, что я не уверен, как преодолеть или подключиться к подстановкам/унификации.
Любая идея, как алгоритм должен быть скорректирован для правильной печати x::Uint
?Или это свойство системы HM и просто не будет вводить такой случай (что я сомневаюсь)?
Обратите внимание, что это было бы совершенно нормально со стандартом let
, но я не хотел обфускать пример с помощью рекурсивных определений, которые не могут обрабатываться let
.
Заранее спасибо