Как Haskell добавил полноту по Тьюрингу в System F?

Я читал о различных системах типов и лямбда-исчислениях и вижу, что все типизированные лямбда-исчисления в лямбда-кубе сильно нормализуются, а не эквивалентны по Тьюрингу. Это включает Систему F, простейшее лямбда-исчисление плюс полиморфизм.

Это приводит меня к следующим вопросам, на которые я не смог найти ни одного приемлемого ответа:

  • Чем отличается формализм (например, Хаскелла) от исчисления, на котором оно якобы основано?
  • Какие языковые возможности в Haskell не подпадают под формализм System F?
  • Какое минимальное изменение необходимо для полного вычисления Тьюринга?

Большое спасибо тому, кто помогает мне понять это.

1 ответ

Решение

Одним словом, общая рекурсия.

Haskell допускает произвольную рекурсию, в то время как System F не имеет формы рекурсии. Отсутствие бесконечных типов означает fix не выражается как закрытый термин.

Нет примитивного понятия имен и рекурсии. На самом деле, чистая Система F не имеет понятия о таких вещах, как определения!

Так что в Хаскеле это единственное определение - то, что добавляет тьюринговую полноту

fix :: (a -> a) -> a
fix f = let x = f x in x

На самом деле эта функция указывает на более общую идею: имея полностью рекурсивные привязки, мы получаем полноту Тьюринга. Обратите внимание, что это относится к типам, а не только к значениям.

data Rec a = Rec {unrec :: Rec a -> a}

y :: (a -> a) -> a
y f = u (Rec u)
  where u x = f $ unrec x x

С бесконечными типами мы можем написать Y комбинатор (по модулю некоторого разворачивания) и через него общую рекурсию!

В чистой Системе F у нас часто есть неформальное представление об определениях, но это просто короткие строки, которые должны быть полностью умственно выделены. Это невозможно в Хаскеле, так как это создаст бесконечные условия.

Ядро терминов Haskell без какого-либо понятия let, where или же = сильно нормализуется, так как у нас нет бесконечных типов. Даже это базовое исчисление терминов на самом деле не является Системой F. Система F имеет "большие лямбды" или абстракцию типов. Полный срок для id в системе F есть

id := /\ A -> \(x : A) -> x

Это потому что вывод типа для System F неразрешим! Мы явно указываем, где и когда мы ожидаем полиморфизма. В Хаскеле такое свойство было бы раздражающим, поэтому мы ограничиваем власть Хаскелла. В частности, мы никогда не выводим полиморфный тип для лямбда-аргумента Haskell без аннотации (могут применяться условия). Вот почему в ML и Haskell

let x = exp in foo

не то же самое, что

(\x -> foo) exp

даже когда exp не рекурсивно! Это суть вывода типа HM и алгоритма W, называемого "пусть обобщением".

Другие вопросы по тегам