Некоторые хотели бы задавать вопросы об этой вещи, но не считают себя достаточно сведущими; попытаемся исправить это.
§1. RTLНачнём с двух классических формальных систем и разовьём их дальше достаточно естественным образом. Первая — пожалуй, самое легковесное небесполезное логическое исчисление,
positive implicational calculus. Это исчисление умеет «обрабатывать» лишь импликацию в высказываниях — всё не содержащее импликацию считается атомарными высказываниями, берущимися из некоторого множества
(sentences). Язык
, с которым работает это исчисление, крайне прост и задаётся такими
правилами образования (formation rules):
Эти правила эквивалентны индуктивному определению
как наименьшего множества, включающего каждый элемент
и для каждых двух своих элементов
также конструкцию вида
.
(Что такое «конструкция»?)
От подобных конструкций требуется естественные вещи:
(1) Надо чтобы
не совпадало ни с какой конструкцией
не вида
— в данном случае с
.
(2) Совпадение
и
экстенсионально, то есть эквивалентно одновременному
и
.
То есть между собой эти штуки работают как кортежи, но мы можем ввести много видов разных кортежей и будем записывать их человеческим образом, а не в виде, например,
.
Индуктивность определения означает, что для любого
мы можем установить, по какому правилу оно было построено и, более общо, что нам доступна
структурная индукция:
Если
для любого выполнено ;
для любых , для которых верны, выполняется и ;
то выполняется на всём .
(Например, индукция (не «полная») по натуральным числам — это структурная индукция по языку, задаваемого правилами
. «Курицу или яйцо», однако, обсуждать тут не будем — это просто пример, и корректный пример; сведение не эквивалентно переопределению.)
Вернёмся к исчислению. Язык мы задали — кстати, его элементы будем звать
формулами — и теперь зададим
выводимость формул. Итак,
правила вывода (inference rules):
Значок
читается «выводимо». MP — сокращение от
Modus ponens, восходящего к названиям правил вывода средневековыми логиками. (Оно пережило все остальные.) Правила вывода может быть удобно переписать более компактно, выкинув очевидные предположения:
Выводом формулы
в этом исчислении мы будем называть получение
путём применения этих правил. Выводы можно изображать в виде деревьев, но это быстро станет неудобным, и я даже не хочу набирать вывод формулы
(где
— вообще любая формула: вывод структурно будет один и тот же — применение одинаковых правил в одинаковых местах), хотя он небольшой.
Потому давайте подумаем, что можно сделать, чтобы писать проще. Можно заметить, что выводы точно так же можно считать индуктивно конструируемыми из других выводов, как это было с определением формул: каждое правило вывода порождает «правило образования вывода» механически. Расширим нотацию и будем писать
для «
получается выводом
» или, лучше «вывод
показывает
». И:
• Правило
превращается в правило
.
• Правило
даёт
.
• Наконец, правило
даёт более интересное
— тут мы собираем два вывода в один.
Теперь я могу вам сказать, что вывод
— это
. Из
и
мы получим
, после чего возьмём
и применив снова MP получим
. Эзотерично (например, я сейчас получил этот вывод, восстанавливая формулы по запомненной схеме самого вывода, и какое-то особое смысловое наполнение в структуре самих формул или вывода искать не стоит), но полностью корректно. И заметьте, что если принять импликацию правоассоциирующей (то есть позволять писать
вместо
), прозрачность формул из как минимум этого вывода упростится (дальше я постараюсь опускать все скобки в таких случаях, крепитесь).
Теперь мы можем коротко (ну, почти коротко — дальше мы это дело чуть улучшим) записывать выводы формул с импликацией. Тут можно было бы доказать, что мы можем вывести все такие формулы, которые истинны при любых значениях истинности атомарных высказываний из
, но это другая история.
§2. LTRНе эта. Эта история будет о другом формализме, λ-исчислении. Возникло оно далеко не с нуля, но мы будем считать его одной из формализаций вычисления, и по желанию формализацией подстановки. Оно чуть сложнее, и потому хорошо, что я показал вам определения с правилами выше.
Язык
определим опять же основываясь на некотором множестве атомов — переменных
:
(напоминаю, части «
» выше опущены!).
Немного о семантике (в §1 семантику импликации вы наверняка уже знали заранее). Элементы этого языка,
λ-термы, можно понимать как некоторые вычисляющие устройства, могущие принять что-то на вход и построить какой-то результат, вход и результат притом те же λ-термы. Терм
— это применение
(функции) к
(аргументу), а терм
— это функция такая, что
— это результат замены в
всех свободных вхождений
на
, причём как раз выражения
считаются связывающими
в
. Если обозначить упомянутую выше замену как
(слэш при этом можно читать как «вместо»), можно определить её рекурсивно. Сначала определим свободные переменные терма
:
•
;
•
;
•
.
Теперь подстановка
:
•
есть
, если
, в противном же случае
;
•
есть
;
• если
,
есть
.
• иначе, в случае
имеем просто
;
• наконец, если
, то
, где
не встречается свободно нигде в
, «свежая», — это делается, чтобы не замкнуть свободные вхождения
из
. Этого неприятного случая можно было бы избежать, отказавшись от связанных переменных, но в данном тексте альтернативный подход (приписывается де Брёйну) скорее всего будет менее понятным. Переименование связанной переменной
в
носит ещё название α-конверсии.
Итак, неформально терм
«вычисляется» в
. Формально это описывается правилами β-редукции:
и стрелка
здесь означает отношение вычислимости за один шаг (а для рассмотрения вычислимости за произвольное число шагов можно использовать его рефлексивное транзитивное замыкание
).
Можно заметить, что есть термы, которые можно вычислять бесконечно, например
, для которого имеем
(за шаг!). Эти
расходящиеся термы неизбежны, если мы хотим использовать это исчисление как тьюринг-полный вычислительный формализм, но можно поставить и другие цели. Например можно захотеть, чтобы любой терм без свободных переменных (
замкнутый) мог интерпретироваться как функция из (и в) какого-то более узкого, чем всё
, множества.
(Да?)
Да. Например, мы можем выделить множество замкнутых термов, которые не редуцируются дальше — считать их чем-то вроде констант. Или расширить язык, включив туда настоящие константы типа
или
.
Подобно конструкции
мы можем захотеть сопоставить «функциональному» терму
тип:
, притом так, чтобы если
, то
, ну и кроме того чтобы вычисление не меняло типа: если
и
, то
. Это возможно.
Определим множество типов
следующими правилами:
где
— некоторое множество переменных-типов. Так как мы не добавляем в язык никаких посторонних констант (см. спойлер чуть выше), без этих переменных не обойтись — надо с чего-то начинать построение.
Чтобы теперь сделать термы типируемыми, подействуем наиболее прямым способом: чуть изменим сам язык термов и будем указывать тип аргумента:
. Кроме того нам понадобится типировать незамкнутые термы, а потому указывать приписанные переменным типы. Это можно делать слева от знака выводимости, например,
, и в общем случае слева скопится какое-то множество
таких утверждений о переменных; заодно давайте писать коротко
для
, когда
, и не писать
слева от
. Правила типирования очень похожи на правила образования термов:
а также надо будет чуть поправить правила
и
(туда входит λ-абстракция, форму которой мы усложнили).
Надо заметить, что мы немного испортили язык: у нас теперь, например, для каждого
есть свой отдельный терм
типа
, когда в бестиповом исчислении был один. Это ничего, и даже бывает полезно. Зато можно убедиться (структурной индукцией, разумеется), что вычисление не портит тип. Кроме того можно видеть, что
не типируется: мы не можем найти никаких типов
, даже для типирования его «половинки»
. Без введения конструкции let (которую мы не будем здесь рассматривать) мы не сможем написать и типируемый комбинатор неподвижной точки (такой замкнутый
, что
), это косвенный признак потери тьюринг-полноты. Ещё надо отметить, что если терм типируется, то единственным образом (по поводу этого и многого другого можно смотреть например [TaPL]).
[TaPL]: Benjamin C. Pierce. Types and programming languages.Теперь если бы мы например добавили тип
со значениями
(два правила образования термов и два правила типирования) и по функции
для каждого
(опять по правилу для того и сего), и дополнили бы правила редукции правилом вычисления выражений
, мы бы могли точно знать, что терм типа
реализует (здесь пока не частичную, при дальнейшем расширении не обязательно) функцию
, и т. д..
§3. → ←Надеюсь, вы к этому моменту покрутили пост туда-сюда и заметили сходство правил
и
и сходство индуктивных определений
и
? Вот. Вы переоткрыли соответствие Карри—Говарда в самой минимальной форме и наверняка даже видите, что удивляться (по крайней мере сейчас тут) особо нечему.
Назовём тип
населённым, если мы можем показать какой-то замкнутый терм с таким типом, то есть
. Теперь мы можем читать эту последнюю запись как «
— доказательство населённости
». Мы можем установить, что термы
и
типизируемы и показывают соответственно аксиомы
и
выше. Показывают в том смысле, что если сформулировать логическое исчисление из §1 полностью аналогично λ-исчислению, эти две аксиомы станут не нужны (в отличие от правила MP и нового правила дедукции, соответствующего
).
Такая теория называется натуральной дедукцией (тут мы получим её урезанный вариант, говорящий только об импликации), и в классическом представлении имеет в правилах вывода посылки не только в виде формул, но и в виде подвыводов из гипотез, где последние «заряжаются» специальными маркерами и «разряжаются» вместе с ними при использовании правила дедукции, и любой вывод зависит ото всех ещё не разряженных в нём гипотез. Контексты типирования в λ-исчислении — это как раз перечисление таких маркеров (имена переменных) и гипотез (их типы).
§4. ???-- Ср июн 26, 2019 03:11:51 --Да, тут ещё должно будет появиться описание того, чему соответствует вычисление в логическом формализме — мы его показали только в §2, а в §1 его аналога нет. Это позже.
-- Ср июн 26, 2019 03:19:45 --Ещё будет показано это:
Однако у этой парочки есть смысл в переписывании произвольного комбинатора, записанного как λ-терм, в запись из K и S без лямбд. И эта процедура соотносится с доказательством леммы о дедукции. Да, надо будет это тоже включить в ту тему.