Лямбда-исчисление - Lambda calculus

Лямбда исчисление (также записываются в виде Л-исчисление ) представляет собой формальная система , в математической логике для выражения вычисления на основе функции абстракции и приложение , используя переменные связывания и замену . Это универсальная модель вычислений, которую можно использовать для моделирования любой машины Тьюринга . Он был введен математиком Алонсо Черчем в 1930-х годах в рамках его исследования основ математики .

Лямбда-исчисление состоит из построения лямбда-членов и выполнения над ними операций редукции. В простейшей форме лямбда-исчисления термины строятся с использованием только следующих правил:

Синтаксис Имя Описание
Икс Переменная Символ или строка, представляющая параметр или математическое / логическое значение.
x . M ) Абстракция Определение функции ( M - лямбда-термин). Переменная x становится связанной в выражении.
( M N ) заявка Применение функции к аргументу. M и N - лямбда-термины.

продуцирующие такие выражения, как: (λ ху . (Х г . (λ х . гй ) (λ у . ZY )) ( х )). Скобки можно опустить, если выражение однозначно. Для некоторых приложений могут быть включены термины для логических и математических констант и операций.

Операции восстановления включают:

Операция Имя Описание
x . M [ x ]) → (λ y . M [ y ]) α-преобразование Переименование связанных переменных в выражении. Используется, чтобы избежать коллизии имен .
((λ x . M ) E ) → ( M [ x  : = E ]) β-редукция Замена связанных переменных выражением аргумента в теле абстракции.

Если используется индексирование по Де Брёйну , то α-преобразование больше не требуется, поскольку не будет конфликтов имен. Если повторное применение шагов редукции в конце концов прекратится, то по теореме Черча – Россера это приведет к β-нормальной форме .

Имена переменных не требуются при использовании универсальной лямбда-функции, такой как Iota и Jot , которая может создавать любое поведение функции, вызывая ее в различных комбинациях.

Объяснение и приложения

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

Лямбда-исчисление может быть нетипизированным или типизированным . В типизированном лямбда-исчислении функции могут применяться только в том случае, если они способны принимать заданный "тип" входных данных. Типизированные лямбда-исчисления слабее, чем нетипизированное лямбда-исчисление, которое является основной темой этой статьи, в том смысле, что типизированные лямбда-исчисления могут выразить меньше, чем нетипизированное исчисление, но, с другой стороны, типизированные лямбда-исчисления позволяют доказать больше. ; в простом типизированном лямбда-исчислении это, например, теорема, что каждая стратегия оценки завершается для каждого просто типизированного лямбда-члена, тогда как оценка нетипизированных лямбда-членов не должна завершаться. Одной из причин, по которой существует множество различных типизированных лямбда-исчислений, было желание сделать больше (того, что может делать нетипизированное исчисление), не отказываясь от возможности доказать сильные теоремы об исчислении.

Лямбда-исчисление находит применение во многих областях математики , философии , лингвистики и информатики . Лямбда-исчисление сыграло важную роль в развитии теории языков программирования . Языки функционального программирования реализуют лямбда-исчисление. Лямбда-исчисление также является актуальной темой исследований в теории категорий .

История

Лямбда-исчисление было введено математиком Алонсо Черчем в 1930-х годах в рамках исследования основ математики . Исходная система оказалась логически несовместимой в 1935 году, когда Стивен Клини и Дж. Б. Россер разработали парадокс Клини – Россера .

Впоследствии, в 1936 году, Черч выделил и опубликовал только ту часть, которая имеет отношение к вычислениям, то, что сейчас называется нетипизированным лямбда-исчислением. В 1940 году он также представил более слабую в вычислительном отношении, но логически последовательную систему, известную как просто типизированное лямбда-исчисление .

До 1960-х годов, когда было выяснено его отношение к языкам программирования, лямбда-исчисление было всего лишь формализмом. Благодаря приложениям Ричарда Монтегю и других лингвистов к семантике естественного языка лямбда-исчисление стало занимать почетное место как в лингвистике, так и в информатике.

Происхождение символа лямбда

Существует некоторая неопределенность в отношении причины использования Черчем греческой буквы лямбда (λ) в качестве обозначения абстракции функции в лямбда-исчислении, возможно, частично из-за противоречивых объяснений самого Черча. Согласно Кардоне и Хиндли (2006):

Кстати, почему Черч выбрал обозначение «λ»? В [неопубликованном письме 1964 года Харальду Диксону] он ясно заявил, что это произошло из обозначения « », используемого для абстракции класса Уайтхедом и Расселом , сначала изменив « » на « », чтобы отличить абстракцию функции от абстракции класса, а затем измените «∧» на «λ» для облегчения печати.

Об этом происхождении также сообщалось в [Россер, 1984, с.338]. С другой стороны, в последние годы своей жизни Черч сказал двум вопрошающим, что выбор был более случайным: нужен был символ и просто случайно был выбран λ.

Дана Скотт также обращалась к этому вопросу в различных публичных лекциях. Скотт вспоминает, что однажды он задал вопрос о происхождении лямбда-символа зятю Черча Джону Аддисону, который затем написал своему тестю открытку:

Уважаемый профессор Черч,

У Рассела был оператор йота , у Гильберта был оператор эпсилон . Почему вы выбрали лямбду для своего оператора?

По словам Скотта, весь ответ Черча состоял в том, чтобы вернуть открытку со следующей пометкой : « Ини, миини, мини, мо ».

Неформальное описание

Мотивация

Вычислимые функции - это фундаментальное понятие в компьютерных науках и математике. Лямбда-исчисление обеспечивает простую семантику вычислений, позволяя формально изучать свойства вычислений. Лямбда-исчисление включает два упрощения, которые упрощают эту семантику. Первое упрощение состоит в том, что лямбда-исчисление обрабатывает функции «анонимно», не давая им явных имен. Например, функция

можно переписать в анонимной форме как

(который читается как « кортеж из х и у будет отображаться в »). Аналогично функция

можно переписать в анонимной форме как

где ввод просто сопоставляется сам с собой.

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

может быть переработан в

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

Функция применения в функции аргументов (5, 2), дает сразу

,

тогда как оценка каррированной версии требует еще одного шага

// определение было использовано во внутреннем выражении. Это похоже на β-редукцию.
// определение было использовано с . Опять же, аналогично β-редукции.

чтобы прийти к тому же результату.

Лямбда-исчисление

Лямбда-исчисление состоит из языка лямбда-терминов , которые определяются определенным формальным синтаксисом, и набора правил преобразования, которые позволяют манипулировать лямбда-терминами. Эти правила преобразования можно рассматривать как эквациональную теорию или как операционное определение .

Как описано выше, все функции в лямбда-исчислении являются анонимными функциями, не имеющими имен. Они принимают только одну входную переменную, а каррирование используется для реализации функций с несколькими переменными.

Лямбда-термины

Синтаксис лямбда-исчисления определяет некоторые выражения как допустимые выражения лямбда-исчисления, а некоторые - как недопустимые, точно так же, как некоторые строки символов являются допустимыми программами C , а некоторые - нет. Правильное выражение лямбда-исчисления называется «лямбда-членом».

Следующие три правила дают индуктивное определение, которое можно применять для построения всех синтаксически правильных лямбда-терминов:

  • переменная ,, сама по себе является допустимым лямбда-термином
  • если является лямбда-термином и является переменной, то (иногда записывается в ASCII как ) является лямбда-термином (называемым абстракцией );
  • если и являются лямбда-терминами, то это лямбда-термин (называемый приложением ).

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

Абстракции является определение анонимной функции, которая способна принимать один вход и подставив в выражение . Таким образом, он определяет анонимную функцию, которая принимает и возвращает . Например, это абстракция функции, использующей термин для . Определение функции с абстракцией просто «устанавливает» функцию, но не вызывает ее. Абстракция связывает переменную в термине .

Приложение представляет собой применение функции к входу , то есть, он представляет акт вызова функции на вход , чтобы произвести .

В лямбда-исчислении не существует концепции объявления переменных. В таком определении, как (т.е. ), лямбда-исчисление рассматривается как переменная, которая еще не определена. Абстракция синтаксически верна и представляет функцию, которая добавляет свой ввод к еще неизвестному .

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

Функции, которые работают с функциями

В лямбда-исчислении функции считаются « значениями первого класса », поэтому функции могут использоваться в качестве входных данных или возвращаться в качестве выходных данных из других функций.

Так , например, представляет собой функцию тождества , и представляет собой функцию тождества применяется к . Кроме того, представляет постоянную функцию , функцию, которая всегда возвращает , независимо от ввода. В лямбда - исчислении применение функции рассматриваются как левоассоциативные , так что средства .

Существует несколько понятий «эквивалентности» и «редукции», которые позволяют «свести» лямбда-термины к «эквивалентным» лямбда-членам.

Альфа-эквивалентность

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

Для определения β-редукции необходимы следующие определения:

Бесплатные переменные

В свободном переменных из термина являются теми переменными , которые не связаны абстракциями. Набор свободных переменных выражения определяется индуктивно:

  • Свободные переменные просто
  • Набор свободных переменных - это набор свободных переменных , но с удаленными
  • Множество свободных переменных в - это объединение множества свободных переменных в и множества свободных переменных в .

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

Замены с избеганием захвата

Предположим , что и являются лямбда-членами, а и являются переменными. Обозначение указывает на то замещение для в в захвата избегающих образом. Это определяется так, что:

  • ;
  • если ;
  • ;
  • ;
  • если и нет в свободных переменных . Переменная считается "свежей" для .

Например , и .

Условие свежести (требующее, чтобы оно не входило в свободные переменные ) имеет решающее значение для гарантии того, что подстановка не изменит смысл функций. Например, замена сделана , что игнорирует свежесть условия: . Эта подстановка превращает постоянную функцию в тождественную путем подстановки.

В общем, несоблюдение условия свежести можно исправить путем альфа-переименования с подходящей переменной fresh. Например, вернувшись к нашему правильному понятию подстановки, в абстракции можно переименовать новую переменную , чтобы получить , и значение функции сохраняется путем подстановки.

β-редукция

Правило β-редукции гласит, что применение формы сводится к члену . Обозначение используется, чтобы указать, что β-сводится к . Например, для каждого , . Это демонстрирует, что это действительно личность. Точно так же, что демонстрирует, что это постоянная функция.

Лямбда-исчисление можно рассматривать как идеализированную версию функционального языка программирования, такого как Haskell или Standard ML . С этой точки зрения β-редукция соответствует вычислительному шагу. Этот шаг можно повторять с помощью дополнительных β-редукций, пока не останется больше приложений для уменьшения. В нетипизированном лямбда-исчислении, представленном здесь, этот процесс редукции не может завершиться. Например, рассмотрим термин . Вот . То есть этот член сводится к самому себе за одно β-восстановление, и, следовательно, процесс восстановления никогда не завершится.

Другой аспект нетипизированного лямбда-исчисления заключается в том, что оно не делает различий между разными типами данных. Например, может быть желательно написать функцию, которая работает только с числами. Однако в нетипизированном лямбда-исчислении нет способа предотвратить применение функции к значениям истинности , строкам или другим нечисловым объектам.

Формальное определение

Определение

Лямбда-выражения состоят из:

  • переменные v 1 , v 2 , ...;
  • символы абстракции λ (лямбда) и. (точка);
  • скобки ().

Набор лямбда-выражений Λ можно определить индуктивно :

  1. Если x - переменная, то x ∈ Λ.
  2. Если x - переменная и M ∈ Λ, то x . M ) ∈ Λ.
  3. Если M , N ∈ Λ, то ( MN ) ∈ Λ.

Экземпляры правила 2 известны как абстракции, а экземпляры правила 3 ​​называются приложениями .

Обозначение

Чтобы не загромождать нотацию лямбда-выражений, обычно применяются следующие соглашения:

  • Крайние круглые скобки опускаются: M N вместо ( M N ).
  • Заявки считаются левоассоциативно: М Н Р может быть записан вместо (( М N ) P ).
  • Тело абстракции простирается как можно дальше вправо : λ x . МН означает λ х . ( МН ) , а не (λ х . М ) Н .
  • Сжимается последовательность абстракций: λ xyz . N сокращенно обозначается λ xyz . N .

Свободные и связанные переменные

Говорят, что оператор абстракции λ связывает свою переменную везде, где она встречается в теле абстракции. Переменные, попадающие в область действия абстракции, называются связанными . В выражении λ x . М , то часть λ х часто называют связующее , как намек , что переменное й становится связанным с добавлением λ х к М . Все остальные переменные называются свободными . Например, в выражении λ y . xxy , y - связанная переменная, а x - свободная переменная. Также переменная привязана к ближайшей абстракции. В следующем примере единственное вхождение x в выражение связано со второй лямбдой: λ x . ух . zx ).

Набор свободных переменных лямбда-выражения M обозначается как FV ( M ) и определяется рекурсией по структуре терминов следующим образом:

  1. FV ( x ) = { x }, где x - переменная.
  2. FV (λ x . M ) = FV ( M ) \ { x }.
  3. FV ( MN ) = FV ( M ) ∪ FV ( N ).

Выражение, не содержащее свободных переменных, называется закрытым . Замкнутые лямбда-выражения также известны как комбинаторы и эквивалентны терминам комбинаторной логики .

Снижение

Значение лямбда-выражений определяется тем, как выражения могут быть сокращены.

Есть три вида сокращения:

  • α-преобразование : изменение связанных переменных;
  • β-редукция : применение функций к их аргументам;
  • η-редукция : захватывает понятие протяженности.

Мы также говорим о результирующих эквивалентностях: два выражения являются α-эквивалентными , если их можно α-преобразовать в одно и то же выражение. Аналогично определяются β-эквивалентность и η-эквивалентность.

Термин « редекс» , сокращение от сокращаемого выражения , относится к подтерминам, которые могут быть сокращены с помощью одного из правил сокращения. Так , например, (λ х . М ) Н является β-REDEX в выражении о замене N для й в М . Выражение, к которому сводится редекс, называется его редукцией ; редукция (λ x . M ) N есть M [ x  : = N ].

Если x не свободен в M , λ x . М х также η-REDEX, с редуктом М .

α-преобразование

α-преобразование, иногда известное как α-переименование, позволяет изменять имена связанных переменных. Например, α-преобразование λ x . x может дать λ y . у . Термины, отличающиеся только α-преобразованием, называются α-эквивалентными . Часто при использовании лямбда-исчисления α-эквивалентные термины считаются эквивалентными.

Точные правила α-преобразования не совсем тривиальны. Во-первых, при α-преобразовании абстракции переименовываются только вхождения переменных, которые связаны с той же абстракцией. Например, α-преобразование λ xx . x может привести к λ yx . х , но это может не привести к λ ух . у . Последний имеет значение, отличное от оригинала. Это аналогично программному понятию затенения переменных .

Во-вторых, α-преобразование невозможно, если оно приведет к захвату переменной другой абстракцией. Например, если мы заменим x на y в λ xy . x , получаем λ yy . y , что совсем не одно и то же.

В языках программирования со статической областью видимости α-преобразование может использоваться для упрощения разрешения имен , гарантируя, что никакое имя переменной не маскирует имя в содержащей области (см. Α-переименование, чтобы сделать разрешение имен тривиальным ).

В обозначении индекса Де Брёйна любые два α-эквивалентных термина синтаксически идентичны.

Замена

Замена, написанный М [ V  : = N ], представляет собой процесс замены всех свободных вхождений переменной V в выражении М с выражением N . Подстановка терминов лямбда-исчисления определяется рекурсией по структуре терминов следующим образом (примечание: x и y - только переменные, а M и N - любое лямбда-выражение):

x [ x  : = N ] = N
y [ x  : = N ] = y , если xy
( M 1 M 2 ) [ x  : = N ] = ( M 1 [ x  : = N ]) ( M 2 [ x  : = N ])
x . M ) [ x  : = N ] = λ x . M
y . M ) [ x  : = N ] = λ y . ( M [ x  : = N ]), если xy и y ∉ FV ( N )

Чтобы заменить абстракцию, иногда необходимо α-преобразовать выражение. Например, неверно для (λ x . Y ) [ y  : = x ] приводить к λ x . x , потому что замененный x должен был быть свободным, но в итоге оказался связанным. Правильная подстановка в этом случае - λ z . x , с точностью до α-эквивалентности. Подстановка определяется однозначно с точностью до α-эквивалентности.

β-редукция

β-редукция отражает идею применения функции. β-восстановительный определяется в терминах Замена: β-восстановительный (λ V . M ) N является М [ V  : = N ].

Например, предполагая некоторую кодировку 2, 7, ×, мы имеем следующую β-редукцию: (λ n . N × 2) 7 → 7 × 2.

β-редукция может рассматриваться как то же самое, что и концепция локальной сводимости в естественной дедукции , через изоморфизм Карри – Ховарда .

η-редукция

η-редукция выражает идею протяженности , которая в данном контексте состоит в том, что две функции одинаковы тогда и только тогда, когда они дают одинаковый результат для всех аргументов. η-редукция преобразует λ x . f x и f всякий раз, когда x не появляется свободным в f .

Можно увидеть, что η-редукция совпадает с концепцией локальной полноты в естественной дедукции через изоморфизм Карри – Ховарда .

Нормальные формы и слияние

Для нетипизированного лямбда-исчисления β-редукция как правило переписывания не является ни строго нормализующим, ни слабо нормализующим .

Однако можно показать, что β-восстановление сливается при работе до α-преобразования (т. Е. Мы считаем две нормальные формы равными, если возможно α-преобразовать одну в другую).

Следовательно, как сильно нормализующие члены, так и слабо нормализующие члены имеют единственную нормальную форму. Для строго нормализующих членов любая стратегия редукции гарантированно дает нормальную форму, тогда как для слабо нормализующих членов некоторые стратегии редукции могут не найти ее.

Кодирование типов данных

Базовое лямбда-исчисление может использоваться для моделирования логических значений, арифметики , структур данных и рекурсии, как показано в следующих подразделах.

Арифметика в лямбда-исчислении

Существует несколько возможных способов определения натуральных чисел в лямбда-исчислении, но наиболее распространенными являются числа Чёрча , которые можно определить следующим образом:

0: = λ f. Λ x . Икс
1: = λ f. Λ x . f x
2: = λ f. Λ x . f ( f x )
3: = λ f. Λ x . f ( f ( f x ))

и так далее. Или используя альтернативный синтаксис, представленный выше в Обозначении :

0: = λ fx . Икс
1: = λ fx . f x
2: = λ fx . f ( f x )
3: = λ fx . f ( f ( f x ))

Числительное Чёрча - это функция высшего порядка: она принимает функцию с одним аргументом f и возвращает другую функцию с одним аргументом. Число Чёрча n - это функция, которая принимает функцию f в качестве аргумента и возвращает n-ю композицию f , то есть функцию f, составленную из самой себя n раз. Это обозначается f ( n ) и фактически является n-й степенью f (рассматриваемой как оператор); f (0) определяется как функция идентичности. Такие повторяющиеся композиции (одной функции f ) подчиняются законам экспонент , поэтому эти числа можно использовать для арифметики. (В исходном лямбда-исчислении Черча формальный параметр лямбда-выражения должен был встречаться хотя бы один раз в теле функции, что делало приведенное выше определение 0 невозможным.)

Число Чёрча n , которое часто бывает полезно при анализе программ, можно рассматривать как инструкцию «повторить n раз». Например, используя функции PAIR и NIL, определенные ниже, можно определить функцию, которая создает (связанный) список из n элементов, все равные x , повторяя «добавить еще один элемент x » n раз, начиная с пустого списка. Лямбда-член

λ пх . n (PAIR x ) NIL

Изменяя то, что повторяется, и варьируя аргумент, к которому применяется эта повторяющаяся функция, можно достичь множества различных эффектов.

Мы можем определить функцию-преемник, которая принимает число Чёрча n и возвращает n + 1 , добавляя еще одно приложение f , где '(mf) x' означает, что функция 'f' применяется m раз к 'x':

SUCC: = λ nfx . f ( n f x )

Поскольку m -я композиция f, составленная с n -ой композицией f, дает m + n -ю композицию f , сложение может быть определено следующим образом:

ПЛЮС: = λ mnfx . м ж ( п е х )

PLUS можно рассматривать как функцию, принимающую в качестве аргументов два натуральных числа и возвращающую натуральное число; можно проверить, что

PLUS 2 3

а также

5

являются β-эквивалентными лямбда-выражениями. Поскольку прибавление m к числу n может быть выполнено добавлением 1 m раз, альтернативное определение:

PLUS: = λ m. Λ n . m SUCC n 

Точно так же умножение можно определить как

MULT: = λ mnf . м ( п ж )

Альтернативно

МУЛЬТ: = λ m. Λ n . м (ПЛЮС n ) 0

так как умножение т и п та же, повторяя адд п функция т раз , а затем применить его к нулю. Возведение в степень выражается довольно просто в числах Чёрча, а именно:

POW: = λ b. Λ e . e b

Функция-предшественник, определенная PRED n = n - 1 для положительного целого числа n и PRED 0 = 0 , значительно сложнее. Формула

PRED: = λ nfx . нгч . ч ( г е )) (λ ц . х ) (λ U . U )

может быть подтверждено , показывая индуктивно , что если Т обозначает гч . ч ( г е )) , то Т ( п )ц . х ) = (λ ч . ч ( е ( п - 1) ( х ))) при n > 0 . Два других определения PRED даны ниже, одно с использованием условных выражений , а другое с использованием пар . С функцией-предшественником вычитание выполняется просто. Определение

SUB: = λ m. Λ n . n ПРЕД м ,

SUB m n дает m - n, если m > n, и 0 в противном случае.

Логика и предикаты

По соглашению для логических значений ИСТИНА и ЛОЖЬ используются следующие два определения (известные как логические значения Черча) :

ИСТИНА: = λ xy . Икс
НЕВЕРНО : = λ xy . у
(Обратите внимание, что FALSE эквивалентно нулю Черча, определенному выше)

Затем с помощью этих двух лямбда-терминов мы можем определить некоторые логические операторы (это всего лишь возможные формулировки; другие выражения также верны):

И: = λ pq . p q p
ИЛИ: = λ p. Λ q . p p q
НЕ: = λ p . p ЛОЖЬ ИСТИНА
IFTHENELSE: = λ pab . п а б

Теперь мы можем вычислять некоторые логические функции, например:

И ИСТИННАЯ ЛОЖЬ
≡ (λ p. Λ q . P q p ) ИСТИНА ЛОЖЬ → β ИСТИНА ЛОЖЬ ИСТИНА
≡ (λ xy . X ) ЛОЖЬ ИСТИНА → β ЛОЖЬ

и мы видим, что AND TRUE FALSE эквивалентно FALSE .

Предикат является функцией , которая возвращает логическое значение. Самым фундаментальным предикатом является ISZERO , который возвращает TRUE, если его аргумент - это число Черча 0 , и FALSE, если его аргумент - любое другое число Черча:

ISZERO: = λ n . nx .FALSE) ИСТИНА

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

LEQ: = λ m. Λ n .ISZERO (SUB m n ) ,

и поскольку m = n , если LEQ m n и LEQ n m , легко построить предикат для числового равенства.

Доступность предикатов и приведенное выше определение ИСТИНА и ЛОЖЬ делают удобной запись выражений «если-то-иначе» в лямбда-исчислении. Например, функцию-предшественницу можно определить как:

PRED: = λ n . пгк .ISZERO ( г 1) к (плюс ( г к ) 1)) (λ v 0,0) 0

что можно проверить, индуктивно показав, что ngk .ISZERO ( g 1) k (PLUS ( g k ) 1)) (λ v .0) является функцией сложения n - 1 для n > 0.

Пары

Пара (2-кортеж) может быть определена в терминах ИСТИНА и ЛОЖЬ , используя кодировку Чёрча для пар . Например, PAIR инкапсулирует пару ( x , y ), FIRST возвращает первый элемент пары, а SECOND возвращает второй.

ПАРА: = λ xyf . f x y
ПЕРВЫЙ: = λ p . p ИСТИНА
ВТОРОЙ: = λ p . p ЛОЖЬ
NIL: = λ x .TRUE
NULL: = λ p . pxy. ЛОЖНО)

Связанный список может быть определен либо как NIL для пустого списка, либо как пара элемента и меньшего списка. Предикат NULL проверяет значение NIL . (В качестве альтернативы, при NIL: = FALSE конструкция lhtz .deal_with_head_ h _and_tail_ t ) (deal_with_nil) устраняет необходимость в явном NULL-тесте).

В качестве примера использования пар функцию сдвига и приращения, которая отображает ( m , n ) в ( n , n + 1), можно определить как

Φ: = λ x .PAIR (ВТОРОЙ x ) (SUCC (ВТОРОЙ x ))

что позволяет нам дать, пожалуй, наиболее прозрачную версию функции-предшественника:

PRED: = λ n. ПЕРВЫЙ ( n Φ (PAIR 0 0)).

Дополнительные техники программирования

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

Именованные константы

В лямбда-исчислении библиотека могла бы иметь форму набора ранее определенных функций, которые в качестве лямбда-терминов являются просто частными константами. Чистое лямбда-исчисление не имеет концепции именованных констант, поскольку все атомарные лямбда-термины являются переменными, но можно имитировать именованные константы, выделив переменную в качестве имени константы, используя абстракцию для привязки этой переменной в основном теле. , и примените эту абстракцию к предполагаемому определению. Таким образом, чтобы использовать f для обозначения M (некоторого явного лямбда-члена) в N (еще один лямбда-термин, «основная программа»), можно сказать

ф . N ) M

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

пусть f = M в N

Объединив такие определения, можно написать «программу» лямбда-исчисления как ноль или более определений функций, за которыми следует один лямбда-член, использующий те функции, которые составляют основную часть программы.

Заметным ограничением этого let является то, что имя f не определено в M , поскольку M находится вне области привязки f абстракции ; это означает, что определение рекурсивной функции не может использоваться как M с let . Более продвинутая конструкция синтаксического сахара letrec, которая позволяет писать определения рекурсивных функций в этом наивном стиле, вместо этого дополнительно использует комбинаторы с фиксированной точкой.

Рекурсия и фиксированные точки

Рекурсия - это определение функции с использованием самой функции. Лямбда-исчисление не может выразить это так же прямо, как некоторые другие обозначения: все функции в лямбда-исчислении анонимны, поэтому мы не можем ссылаться на значение, которое еще не определено, внутри лямбда-члена, определяющего то же значение. Тем не менее, по- прежнему рекурсии может быть достигнуто путем организации лямбда - выражения , чтобы получить себя в качестве аргумента значение, например , в  х . Х х ) Е .

Рассмотрим факториальную функцию F ( n ), рекурсивно определяемую формулой

F ( n ) = 1, если n = 0; иначе n × F ( n - 1) .

В лямбда-выражении, которое должно представлять эту функцию, предполагается, что параметр (обычно первый) принимает само лямбда-выражение в качестве своего значения, так что его вызов - применение его к аргументу - приведет к рекурсии. Таким образом, для достижения рекурсии аргумент, предполагаемый как самореференция ( здесь называется r ), должен всегда передаваться самому себе в теле функции в точке вызова:

G: = λ r . λ n . (1, если n = 0; иначе n × ( r r ( n −1)))
с  r r x = F x = G r x  , поэтому  {{{1}}}  и
F: = GG = (λ x . X x ) G

Самоприложение выполняет здесь репликацию, передавая лямбда-выражение функции следующему вызову в качестве значения аргумента, делая его доступным для ссылки и вызова.

Это решает проблему, но требует перезаписи каждого рекурсивного вызова как самостоятельного приложения. Мы хотели бы иметь общее решение без необходимости переписывать:

G: = λ r . λ n . (1, если n = 0; иначе n × ( r ( n −1)))
с  r x = F x = G r x  , поэтому  r = G r =: FIX G  и
F: = FIX G  где  FIX g  : = ( r, где r = g r ) = g (FIX g )
так что  FIX G = G (FIX G) = (λ n . (1, если n = 0; иначе n × ((FIX G) ( n −1))))

Учитывая лямбда-член с первым аргументом, представляющим рекурсивный вызов (например, здесь G ), комбинатор с фиксированной точкой FIX вернет самовоспроизводящееся лямбда-выражение, представляющее рекурсивную функцию (здесь F ). Функция не нуждается в явной передаче самой себе в любой момент, поскольку саморепликация организована заранее, когда она создается, чтобы выполняться каждый раз при ее вызове. Таким образом, исходное лямбда-выражение (FIX G) воссоздается внутри себя, в точке вызова, с получением ссылки на себя .

Фактически, для этого оператора FIX существует множество возможных определений , самое простое из которых:

Y  : = λ g . (Λ x . G ( x x )) (λ x . G ( x x ))

В лямбда-исчислении Y g   является фиксированной точкой g , поскольку она расширяется до:

Г г
h . (λ x . h ( x x )) (λ x . h ( x x ))) g
x . g ( x x )) (λ x . g ( x x ))
g ((λ x . g ( x x )) (λ x . g ( x x )))
г ( У г )

Теперь, чтобы выполнить наш рекурсивный вызов функции факториала, мы просто вызовем ( Y G) n , где n - это число, для которого мы вычисляем факториал. При п = 4, например, это дает:

( Y G) 4
Г ( Г Г) 4
rn . (1, если n = 0; иначе n × ( r ( n −1)))) ( Y G) 4
n . (1, если n = 0; иначе n × (( Y G) ( n −1)))) 4
1, если 4 = 0; иначе 4 × (( Y G) (4−1))
4 × (G ( Y G) (4-1))
4 × ((λ n . (1, если n = 0; иначе n × (( Y G) ( n −1)))) (4−1))
4 × (1, если 3 = 0; иначе 3 × (( Y G) (3−1)))
4 × (3 × (G ( Y G) (3−1)))
4 × (3 × ((λ n . (1, если n = 0; иначе n × (( Y G) ( n −1)))) (3−1)))
4 × (3 × (1, если 2 = 0; иначе 2 × (( Y G) (2−1))))
4 × (3 × (2 × (G ( Y G) (2−1))))
4 × (3 × (2 × ((λ n . (1, если n = 0; иначе n × (( Y G) ( n −1)))) (2−1))))
4 × (3 × (2 × (1, если 1 = 0; иначе 1 × (( Y G) (1−1)))))
4 × (3 × (2 × (1 × (G ( Y G) (1−1)))))
4 × (3 × (2 × (1 × ((λ n . (1, если n = 0; иначе n × (( Y G) ( n −1)))) (1−1)))))
4 × (3 × (2 × (1 × (1, если 0 = 0; иначе 0 × (( Y G) (0−1))))))
4 × (3 × (2 × (1 × (1))))
24

Каждую рекурсивно определенную функцию можно рассматривать как фиксированную точку некоторой подходящим образом определенной функции, закрывающейся по рекурсивному вызову с дополнительным аргументом, и поэтому, используя Y , каждая рекурсивно определенная функция может быть выражена как лямбда-выражение. В частности, теперь мы можем четко определить предикат вычитания, умножения и сравнения натуральных чисел рекурсивно.

Стандартные условия

У некоторых терминов есть общепринятые названия:

I  : = λ x . Икс
K  : = λ x. Λ y . Икс
S  : = λ x. Λ y. Λ z . х г ( у г )
B  : = λ x. Λ y. Λ z . х ( у z )
C  : = λ x. Λ y. Λ z . х г у
W  : = λ x. Λ y . x y y
U  : = λ x . х х
ω  : = λ x . х х
Ω  : = ω ω
Y  : = λ g . (Λ x . G ( x x )) (λ x . G ( x x ))

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

Устранение абстракции

Если N - лямбда-член без абстракции, но, возможно, содержащий именованные константы ( комбинаторы ), то существует лямбда-член T ( x , N ), который эквивалентен λ x . N, но в нем отсутствует абстракция (кроме как части именованных констант, если они считаются неатомарными). Это также можно рассматривать как анонимизирующие переменные, поскольку T ( x , N ) удаляет все вхождения x из N , при этом позволяя подставлять значения аргументов в позиции, где N содержит x . Функция преобразования T может быть определена следующим образом:

Т ( х , х ): = I
Т ( х , Н ): = К Н , если й не свободны в N .
Т ( х , М N ): = S Т ( х , М ) Т ( х , N )

В любом случае член формы T ( x , N ) P может уменьшаться, если исходный комбинатор I , K или S захватывает аргумент P , точно так же, как это сделало бы β-сокращение x . N ) P. Я возвращаю этот аргумент. K бросает аргумент в стороне, так же , как х . N ) будет делать , если й не имеет свободное вхождения в N . S передает аргумент обоим подтермам приложения, а затем применяет результат первого к результату второго.

Комбинаторы B и C аналогичны S , но передают аргумент только одному подтермину приложения ( B к подтерму «аргумент» и C к подтерму «функция»), таким образом сохраняя последующий K, если нет вхождения из й в одном подтерме. По сравнению с B и C , то S комбинатор фактически смешивает две функциональные возможности : переставляя аргументы, и дублировать аргумент , так что он может быть использован в двух местах. Вт комбинатор делает только последним, получая B, C, K, W систему в качестве альтернативы SKI комбинатора исчисления .

Типизированное лямбда-исчисление

Типизированного лямбда - исчисление является типизированным формализм , который использует лямбда-символ ( ) для обозначения анонимную функцию абстракции. В этом контексте типы обычно являются объектами синтаксического характера, которые присваиваются лямбда-терминам; точная природа типа зависит от рассматриваемого исчисления (см. Виды типизированных лямбда-исчислений ). С определенной точки зрения типизированные лямбда-исчисления можно рассматривать как уточнения нетипизированного лямбда-исчисления, но с другой точки зрения их также можно рассматривать как более фундаментальную теорию, а нетипизированное лямбда-исчисление - как частный случай только с одним типом.

Типизированные лямбда-исчисления являются основополагающими языками программирования и составляют основу типизированных функциональных языков программирования, таких как ML и Haskell, и, что более косвенно, типизированных императивных языков программирования . Типизированные лямбда-исчисления играют важную роль в разработке систем типов для языков программирования; здесь типизируемость обычно фиксирует желаемые свойства программы, например, программа не вызовет нарушения доступа к памяти.

Типизированные лямбда-исчисления тесно связаны с математической логикой и теорией доказательств через изоморфизм Карри – Ховарда, и их можно рассматривать как внутренний язык классов категорий , например, просто типизированное лямбда-исчисление является языком декартовых замкнутых категорий (CCC).

Стратегии сокращения

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

Нормальный порядок
Самый левый, крайний редекс всегда уменьшается первым. То есть, когда это возможно, аргументы подставляются в тело абстракции до того, как аргументы будут сокращены.
Заявочный порядок
Самый левый, самый внутренний редекс всегда уменьшается первым. Интуитивно это означает, что аргументы функции всегда сокращаются перед самой функцией. Аппликативный порядок всегда пытается применить функции к нормальным формам, даже если это невозможно.
Полные β-редукции
Любой редекс можно уменьшить в любой момент. По сути, это означает отсутствие какой-либо конкретной стратегии сокращения - что касается сводимости, «все ставки отключены».

Слабые стратегии сокращения не сводятся к лямбда-абстракциям:

Звоните по цене
Редекс уменьшается только тогда, когда его правая часть уменьшена до значения (переменной или абстракции). Уменьшаются только крайние редексы.
Звоните по имени
Обычный порядок, но внутри абстракций сокращения не выполняются. Например, λ x . (Λ x . X ) x находится в нормальной форме в соответствии с этой стратегией, хотя он содержит redex x . X ) x .

Стратегии с совместным использованием сокращают количество параллельных вычислений, которые "одинаковы":

Оптимальное сокращение
В обычном порядке, но вычисления с одинаковой меткой сокращаются одновременно.
Звоните по необходимости
Как вызов по имени (следовательно, слабый), но приложения-функции, которые будут дублировать термины, вместо этого называют аргумент, который затем сокращается только «тогда, когда это необходимо».

Вычислимость

Не существует алгоритма, который принимает на вход любые два лямбда-выражения и выводит ИСТИНА или ЛОЖЬ в зависимости от того, сводится ли одно выражение к другому. Точнее, никакая вычислимая функция не может решить этот вопрос. Исторически это была первая проблема, неразрешимость которой могла быть доказана. Как обычно для такого доказательства, вычислимость означает вычислимость с помощью любой модели вычислений , полной по Тьюрингу . Фактически, вычислимость может быть определена с помощью лямбда-исчисления: функция натуральных чисел F : NN является вычислимой функцией тогда и только тогда, когда существует лямбда-выражение f такое, что для каждой пары x , y в N , F ( x ) = y тогда и только тогда, когда f x  = β  y , где x и y - числа Чёрча, соответствующие x и y , соответственно, а = β означает эквивалентность с β-редукцией. См. Тезис Черча – Тьюринга, чтобы узнать о других подходах к определению вычислимости и их эквивалентности.

Доказательство невычислимости Черча сначала сводит проблему к определению того, имеет ли данное лямбда-выражение нормальную форму . Затем он предполагает, что этот предикат вычислим и, следовательно, может быть выражен в лямбда-исчислении. Основываясь на более ранней работе Клини и строя нумерацию Гёделя для лямбда-выражений, он строит лямбда-выражение e, которое близко следует доказательству первой теоремы Гёделя о неполноте . Если e применяется к его собственному числу Гёделя, получаем противоречие.

Сложность

Понятие вычислительной сложности для лямбда-исчисления немного сложно, потому что стоимость β-редукции может варьироваться в зависимости от того, как оно реализовано. Чтобы быть точным, нужно каким-то образом найти расположение всех вхождений связанной переменной V в выражении E , подразумевая временные затраты, или нужно каким-то образом отслеживать расположение свободных переменных, подразумевая затраты на пространство. Наивный поиск местоположений V в Е является О ( п ) длины п из Е . Директорные струны были ранним подходом, в котором затраты времени были заменены квадратичным использованием пространства. В более общем плане это привело к изучению систем, использующих явную замену .

В 2014 году было показано, что количество шагов β-редукции, предпринимаемых обычным уменьшением порядка для сокращения члена, является разумной моделью затрат времени, то есть сокращение может быть смоделировано на машине Тьюринга за время, полиномиально пропорциональное количеству шагов. . Это была давняя открытая проблема из-за стремительного роста размеров , существования лямбда-членов, размер которых экспоненциально увеличивается при каждом β-уменьшении. В результате это можно обойти, работая с компактным общим представлением. Результат показывает, что объем пространства, необходимого для оценки лямбда-члена, не пропорционален размеру термина во время сокращения. В настоящее время неизвестно, какова будет хорошая мера сложности пространства.

Необоснованная модель не обязательно означает неэффективность. Оптимальное сокращение сокращает все вычисления с одной и той же меткой за один шаг, избегая дублирования работы, но количество параллельных шагов β-редукции для приведения данного члена к нормальной форме приблизительно линейно по размеру члена. Это слишком мало, чтобы быть разумной мерой затрат, поскольку любая машина Тьюринга может быть закодирована в лямбда-исчислении в размере, линейно пропорциональном размеру машины Тьюринга. Истинная стоимость сокращения лямбда-членов связана не с β-редукцией как таковой, а с обработкой дублирования редексов во время β-редукции. Неизвестно, являются ли оптимальные реализации сокращения разумными при измерении относительно разумной модели затрат, такой как количество крайних левых шагов к нормальной форме, но для фрагментов лямбда-исчисления было показано, что алгоритм оптимального сокращения эффективен. и имеет не более чем квадратичные накладные расходы по сравнению с крайним левым. Вдобавок реализация оптимального сокращения прототипа BOHM превзошла Caml Light и Haskell по чистым лямбда-терминам.

Лямбда-исчисление и языки программирования

Как указано в статье Питера Ландина 1965 года «Соответствие между АЛГОЛОМ 60 и лямбда-нотацией Черча», последовательные процедурные языки программирования можно понимать в терминах лямбда-исчисления, которое обеспечивает основные механизмы процедурной абстракции и процедуры (подпрограммы) заявление.

Анонимные функции

Например, в Лиспе "квадратная" функция может быть выражена как лямбда-выражение следующим образом:

(lambda (x) (* x x))

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

Например, Паскаль и многие другие императивные языки давно поддерживают передачу подпрограмм в качестве аргументов другим подпрограммам через механизм указателей на функции . Однако указатели на функции не являются достаточным условием для того, чтобы функции были типами данных первого класса , потому что функция является типом данных первого класса тогда и только тогда, когда новые экземпляры функции могут быть созданы во время выполнения. И это создание функций во время выполнения поддерживается, в частности , в Smalltalk , JavaScript и Wolfram Language , а в последнее время в Scala , Eiffel («агенты»), C # («делегаты») и C ++ 11 .

Параллелизм и параллелизм

Свойство Чёрча – Россера лямбда-исчисления означает, что вычисление (β-редукция) может выполняться в любом порядке , даже параллельно. Это означает, что актуальны различные недетерминированные стратегии оценки . Однако лямбда-исчисление не предлагает никаких явных конструкций для параллелизма . В лямбда-исчисление можно добавить такие конструкции, как Futures . Для описания взаимодействия и параллелизма были разработаны другие вычисления процессов .

Семантика

Тот факт, что термы лямбда-исчисления действуют как функции на других термах лямбда-исчисления и даже на самих себя, привел к вопросам о семантике лямбда-исчисления. Можно ли придать разумное значение терминам лямбда-исчисления? Естественная семантика заключалась в том, чтобы найти множество D, изоморфное функциональному пространству DD , функций на самом себе. Однако такой нетривиальный D не может существовать из-за ограничений мощности, потому что набор всех функций от D до D имеет большую мощность, чем D , если D не является одноэлементным набором .

В 1970-х Дана Скотт показала, что, если бы рассматривались только непрерывные функции, можно было бы найти набор или область D с требуемым свойством, тем самым предоставив модель лямбда-исчисления.

Эта работа также легла в основу денотационной семантики языков программирования.

Варианты и расширения

Эти расширения находятся в лямбда-кубе :

Эти формальные системы являются расширениями лямбда-исчисления, которых нет в лямбда-кубе:

Эти формальные системы представляют собой разновидности лямбда-исчисления:

Эти формальные системы связаны с лямбда-исчислением:

Смотрите также

Примечания

использованная литература

дальнейшее чтение

Монографии / учебники для аспирантов:

  • Мортен Хайне Соренсен, Павел Уржичин, Лекции по изоморфизму Карри – Ховарда , Elsevier, 2006, ISBN  0-444-52077-5 - это недавняя монография, которая охватывает основные темы лямбда-исчисления от безтипового до наиболее типизированного лямбда. исчисления , включая более свежие разработки, такие как системы чистых типов и лямбда-куб . Он не распространяется на расширения подтипов .
  • Пирс, Бенджамин (2002), Типы и языки программирования , MIT Press, ISBN 0-262-16209-1охватывает лямбда-исчисления с точки зрения системы практических типов; некоторые темы, такие как зависимые типы, только упоминаются, но выделение подтипов является важной темой.

Некоторые части этой статьи основаны на материалах FOLDOC , используемых с разрешения .

внешние ссылки

  1. ^ Церковь, Алонсо (1941). Исчисления лямбда-преобразования . Принстон: Издательство Принстонского университета . Проверено 14 апреля 2020 .
  2. Перейти ↑ Frink Jr., Orrin (1944). "Обзор: исчисления лямбда-преобразования Алонсо Чёрчем" (PDF) . Бык. Амер. Математика. Soc . 50 (3): 169–172. DOI : 10.1090 / s0002-9904-1944-08090-7 .