Найдите наиболее общие типы следующих терминов лямбда-исчисления.

Мне трудно понять, почему это самые общие типы для соответствующих церковных цифр:

2 = λf.λx. f (f x) : (α → α) → α → α 

1 = λf.λx. f x : (α → β) → α → β

0 = λf.λx. x : β → α → α

Я думал, что все числительные Черча имеют один и тот же тип:

(α → α) → α → α 

Также как мне найти общий тип для оператора добавления

λm.λn.λf.λx. m f (n f x)

Любая помощь будет действительно оценена, спасибо!


person user3438924    schedule 09.05.2016    source источник


Ответы (1)


Начнем с числительного Черча для нуля:

λf.λx. x : β → α → α

Глядя только на часть λf.λx., можно сделать вывод, что у нас есть функция с двумя аргументами, следовательно, ее тип — α → β → γ, где α и β обозначают типы аргументов, а γ — тип результата. Теперь тело x дополнительно ограничивает тип: тип возвращаемого значения нашей функции должен быть таким же, как и тип ее второго аргумента. Это приводит к α → β → β или после переименования (α ↔ β): λf.λx. x : β → α → α. Это самый общий тип для нуля, так как мы не использовали тот факт, что f должно быть функцией, на самом деле нулевое число Черча в нетипизированном лямбда-исчислении не заботится: оно просто забывает, что первый аргумент. А поскольку β — это всего лишь заполнитель, вы можете специализировать его на α → α, что приведет к более конкретному типу нуля — λf.λx. x : (α → α) → α → α.

Давайте посмотрим на 1:

λf.λx. f x : (α → β) → α → β

Опять же, это функция с двумя аргументами: α → β → γ, но на этот раз (посмотрите на тело 1) мы знаем, что первый аргумент f — это функция, поэтому f имеет некоторый тип δ → ε, который мы должны заменить на α: (δ → ε) → β → γ. Теперь мы знаем, что мы должны уметь применять f к x, а это значит, что тип x и тип аргумента f должны быть равны: δ = β, таким образом, мы достигли (β → ε) → β → γ. Но это еще не все, что мы знаем, f x имеет тип ε, а наш нумерал возвращает f x, применяя эту информацию, мы получаем ε = γ. Включив все это, мы получаем (β → γ) → β → γ, или после переименования: λf.λx. f x : (α → β) → α → β. Опять же, мы не использовали никакой информации о наших намерениях использования, поэтому у нас самый общий тип и, конечно же, он может быть специализирован (по ограничению β = α) до λf.λx. f x : (α → α) → α → α.

Теперь очередь 2:

λf.λx. f (f x) : (α → α) → α → α

На этот раз я не буду повторять все шаги, но (в качестве промежуточного шага) мы можем прийти к λf.λx. f (f x) : (α → β) → α → β. Обратите внимание, однако, что на этот раз мы передаем результат f самому себе: f (f x), а это означает, что входные и выходные типы f должны быть равны, таким образом, β = α, и на этот раз наиболее общий тип — λf.λx. f (f x) : (α → α) → α → α.

(*) Обратите внимание, что типы 3, 4 и т. д. Черча имеют тот же наиболее общий тип, что и 2, потому что приложения с несколькими функциями не дают нам никакой дополнительной информации для дальнейшей специализации типа.


Что касается функции сложения λm.λn.λf.λx. m f (n f x), позвольте мне быть немного более кратким:

  • Предположим, что выражение имеет тип α → β → γ → δ → ε.
  • m является функцией двух аргументов: α должно быть ограничено до α' → α'' → α'''
  • То же самое для n: β должно быть ограничено до β' → β'' → β'''
  • Первый аргумент m и n имеет тот же тип, что и f: α' = β' = γ
  • Второй аргумент n имеет тип δ.
  • Тип результата n равен второму типу аргумента m: β''' = α''
  • Давайте объединим все вышеперечисленные знания для n : γ → δ → α''
  • То же самое для m : γ → α'' → ε
  • Следовательно, тип результата (γ → α'' → ε) → (γ → δ → α'') → γ → δ → ε

Давайте переименуем переменные, чтобы это выглядело немного красивее:

самый общий тип для λm.λn.λf.λx. m f (n f x) это

(β → γ → ε) → (β → α → γ) → β → α → ε.

Давайте проверим, что это может быть специализировано для того, что можно было бы ожидать, чтобы быть бинарной операцией с числами Чёрча (β = α → α, γ = α, ε = α):

((α → α) → α → α) → ((α → α) → α → α) → (α → α) → α → α.

person Anton Trunov    schedule 09.05.2016
comment
Большое спасибо! Это было очень полезно, я наконец понимаю! - person user3438924; 09.05.2016
comment
в λm.λn.λf.λx. m f (n f x) почему вы не расширили тип f? В этот момент я действительно запутался, так как f - это функция, которая принимает 1 аргумент, который является типом x или типом результата n. Я думал, что для f: y должно быть ограничено α''-> y'' - person alixander; 12.12.2018
comment
@alixander Потому что это не даст нам самый общий тип. Если вы попытаетесь проверить это с помощью интерпретатора Haskell GHCi, используя этот запрос :t \m n f x -> m f (n f x), или на верхнем уровне OCaml с помощью fun m n f x -> m f (n f x);;, вы получите тот же результат, что и в моей рукописной версии (именование по модулю). - person Anton Trunov; 13.12.2018
comment
@AntonTrunov я знаю, что результат правильный. Я уже пробовал это в haskell, но я до сих пор не понимаю, почему тип f не расширяется! - person alixander; 13.12.2018
comment
@alixander f ни к чему не применяется, поэтому у механизма вывода типов нет причин считать его функцией. То, что мы получили, более общее, это по сути композиция из двух функций с общим (для них обоих) «окружением» f. ХТН - person Anton Trunov; 13.12.2018
comment
@AntonTrunov, почему вы считаете, что f ни к чему не применяется? - person alixander; 13.12.2018
comment
@alixander Может ли источник вашего замешательства быть в том, как вы анализируете выражение? В выражении m f (n f x) f ни к чему не применяется. Только m и n есть. n применяется к двум аргументам -- f и x, а m применяется к f и n f x. - person Anton Trunov; 13.12.2018