Исчисление комбинаторов SKI — это комбинаторная логическая система и вычислительная система . Его можно рассматривать как язык программирования компьютеров, хотя он не удобен для написания программного обеспечения. Вместо этого он важен в математической теории алгоритмов , поскольку является чрезвычайно простым полным по Тьюрингу языком. Его можно сравнить с сокращенной версией нетипизированного лямбда-исчисления . Он был введен Моисеем Шёнфинкелем [1] и Хаскеллом Карри [2] .
Все операции в лямбда-исчислении могут быть закодированы посредством исключения абстракций в исчислении SKI в виде бинарных деревьев , листьями которых являются один из трех символов S , K и I (называемых комбинаторами ).
Хотя наиболее формальное представление объектов в этой системе требует бинарных деревьев, для более простого набора они часто представляются в виде выражений в скобках, как сокращение для дерева, которое они представляют. Любые поддеревья могут быть заключены в скобки, но часто в скобки заключаются только правые поддеревья, при этом левая ассоциативность подразумевается для любых не заключенных в скобки приложений. Например, ISK означает (( IS ) K ). Используя эту нотацию, дерево, левое поддерево которого является деревом KS , а правое поддерево — деревом SK, можно записать как KS ( SK ). Если требуется большая ясность, можно также включить подразумеваемые скобки: (( KS )( SK )).
Неформально, и используя жаргон языка программирования, дерево ( xy ) можно рассматривать как функцию x, примененную к аргументу y . При оценке ( т. е . когда функция «применяется» к аргументу) дерево «возвращает значение», т. е . преобразуется в другое дерево. «Функция», «аргумент» и «значение» являются либо комбинаторами, либо бинарными деревьями. Если они являются бинарными деревьями, их также можно рассматривать как функции, если это необходимо.
Операция оценки определяется следующим образом:
( x , y и z представляют собой выражения, составленные из функций S , K и I , и заданных значений):
Я возвращаю свой аргумент:
При применении K к любому аргументу x получается константная функция K x с одним аргументом , которая при применении к любому аргументу y возвращает x :
S — оператор подстановки. Он принимает три аргумента, а затем возвращает первый аргумент, примененный к третьему, который затем применяется к результату второго аргумента, примененного к третьему. Более ясно:
Пример вычисления: SKSK оценивается как KK ( SK ) по правилу S. Затем, если мы оцениваем KK ( SK ), мы получаем K по правилу K. Поскольку никакое другое правило не может быть применено, вычисление останавливается здесь.
Для всех деревьев x и всех деревьев y , SK xy всегда будет оцениваться как y в два шага, K y ( xy ) = y , поэтому конечный результат оценки SK xy всегда будет равен результату оценки y . Мы говорим, что SK x и I «функционально эквивалентны» для любого x , потому что они всегда дают один и тот же результат при применении к любому y .
Из этих определений можно показать, что исчисление SKI не является минимальной системой, которая может полностью выполнять вычисления лямбда-исчисления, поскольку все вхождения I в любом выражении могут быть заменены на ( SKK ) или ( SKS ) или ( SK x ) для любого x , и полученное выражение даст тот же результат. Таким образом, « I » — это просто синтаксический сахар . Поскольку I является необязательным, система также называется исчислением SK или комбинаторным исчислением SK .
Можно определить полную систему, используя только один (несобственный) комбинатор. Примером является йота- комбинатор Криса Баркера, который можно выразить в терминах S и K следующим образом:
Можно восстановить S , K , и I из комбинатора йота. Применение ι к самому себе дает ιι = ι SK = SSKK = SK ( KK ), что функционально эквивалентно I . K можно построить, применив ι дважды к I (что эквивалентно применению ι к самому себе): ι(ι(ιι)) = ι(ιι SK ) = ι( ISK ) = ι( SK ) = SKSK = K . Применение ι еще раз дает ι(ι(ι(ιι))) = ι K = KSK = S .
Простейшим возможным членом , образующим базис, является X = λf.f λxyz.xz (yz) λxyz.x, который удовлетворяет XX = K и X (XX) = S.
Термины и производные в этой системе можно определить и более формально:
Термины : Множество терминов T определяется рекурсивно по следующим правилам.
Выводы : Вывод — это конечная последовательность терминов, определяемая рекурсивно следующими правилами (где α и ι — слова в алфавите { S , K , I , (, )}, а β, γ и δ — термины):
Предполагая, что последовательность является допустимым выводом, ее можно расширить, используя эти правила. Все вывода длины 1 являются допустимыми выводами.
SII — это выражение, которое берет аргумент и применяет этот аргумент к себе:
Это также известно как комбинатор U , U x = xx . Одним из интересных его свойств является то, что его самоприменение неприводимо:
Или, используя уравнение непосредственно в качестве определения, мы немедленно получаем U U = U U .
Другое дело, что он позволяет написать функцию, которая применяет одну вещь к самоприменению другой вещи:
или его можно рассматривать как непосредственное определение еще одного комбинатора, H xy = x ( yy ).
Эта функция может быть использована для достижения рекурсии . Если β — это функция, которая применяет α к самоприменению чего-либо еще,
тогда самоприменение этого β является неподвижной точкой этого α:
Или, снова непосредственно из полученного определения, H α( H α) = α( H α( H α)).
Если α выражает «вычислительный шаг», вычисляемый αρν для некоторых ρ и ν, что предполагает, что ρν' выражает «остальную часть вычисления» (для некоторого ν', которое α «вычислит» из ν), то его неподвижная точка ββ выражает все рекурсивное вычисление, поскольку использование той же функции ββ для вызова «остальной части вычисления» (с ββν = α(ββ)ν) является самим определением рекурсии: ρν' = ββν' = α(ββ)ν' = ... . α придется использовать некое условное выражение, чтобы остановиться на некотором «базовом случае» и не делать рекурсивный вызов затем, чтобы избежать расхождения.
Это можно формализовать,
как
что дает нам одну из возможных кодировок комбинатора Y.
Это становится намного короче с использованием комбинаторов B и C , как эквивалент
или, напрямую используя определение комбинатора H ,
А с помощью псевдо- синтаксиса Haskell это становится исключительно коротким Y = U . (. U ).
Следуя этому подходу, возможны другие определения комбинатора фиксированной точки, например:
или определение любого другого промежуточного комбинатора H (где вместо «_» может использоваться что угодно) с соответствующим ему определением Y для правильного запуска.
S ( K ( SI )) K меняет местами два следующих за ним члена:
Таким образом, он эквивалентен CI . И в общем случае S ( K ( S f )) K эквивалентен C f для любого f .
Исчисление комбинаторов SKI также может реализовывать булеву логику в форме структуры if-then-else . Структура if-then-else состоит из булева выражения, которое является либо истинным ( T ), либо ложным ( F ), и двух аргументов, таких что:
и
Ключ в определении двух булевых выражений. Первое работает так же, как один из наших базовых комбинаторов:
Второй вариант тоже довольно прост:
После определения значений true и false вся булева логика может быть реализована в терминах структур if-then-else .
Логическое НЕ (возвращающее противоположность заданному логическому значению) работает так же, как структура if-then-else , с F и T в качестве второго и третьего значений, поэтому его можно реализовать как постфиксную операцию:
Если это поместить в структуру if-then-else , можно показать, что это дает ожидаемый результат.
Булевое ИЛИ (которое возвращает T, если любое из двух окружающих его булевых значений равно T ) работает так же, как структура if-then-else с T в качестве второго значения, поэтому его можно реализовать как инфиксную операцию:
Если поместить это в структуру if-then-else , можно показать, что это дает ожидаемый результат:
Логическое И (которое возвращает T, если оба из двух окружающих его логических значений равны T ) работает так же, как структура if-then-else с F в качестве третьего значения, поэтому его можно реализовать как постфиксную операцию:
Если поместить это в структуру if-then-else , можно показать, что это дает ожидаемый результат:
Поскольку это определяет T , F , NOT (как постфиксный оператор), OR (как инфиксный оператор) и AND (как постфиксный оператор) в терминах нотации SKI, это доказывает, что система SKI может полностью выражать булеву логику.
Поскольку исчисление SKI является полным , можно также выразить NOT , OR и AND как префиксные операторы:
Комбинаторы K и S соответствуют двум известным аксиомам пропозициональной логики :
Применение функции соответствует правилу modus ponens :
Аксиомы AK и AS , а также правило MP являются полными для импликационного фрагмента интуиционистской логики . Для того, чтобы комбинаторная логика имела в качестве модели:
Эта связь между типами комбинаторов и соответствующими логическими аксиомами является примером изоморфизма Карри–Ховарда .
Может быть несколько способов сделать сокращение. Все они эквивалентны, пока вы не нарушаете порядок операций