
5.2 Комбінатори
Теорія комбінаторів була розроблена ще до створення лямбда-вирахування, але її зручно розглядати саме в термінах лямбда-виразів.
Комбінатором будемо називати лямбда-терм, який не містить вільних змінних. Такий терм є замкненим, він має фіксоване значення незалежно від значень будь-яких змінних.
У теорії комбінаторів установлено, що за допомогою декількох базових комбінаторів і змінних можна виразити будь-який терм без застосування лямбда-абстракції. Зокрема, замкнений терм можна виразити тільки через ці базові комбінатори. Визначимо ці комбінатори таким чином:
I = λx.x,
K = λx. λy.x,
S = λf. λg. λx. f x (g x).
Комбінатор I є функцією ідентичності, яка залишає свій аргумент незмінним. Комбінатор K служить для створення константних функцій. Застосовуючи його до аргументу a, одержимо функцію λx.a , яка повертає a незалежно від переданого їй аргументу. Комбінатор S бере дві функції і аргумент і розділяє його між функціями.
Справедлива теорема: для довільного терма t існує терм t', який не містить лямбда-абстракцій і складається з комбінаторів S, K, I і змінних, такий, що F(t' )= F(t) і t'= t.
Цю теорему можна підсилити, оскільки комбінатор I може бути виражений у термінах S і K. Дійсно, для будь-якого A виконується:
S K A x = K x (A x) = (λy.x) (a x) = x.
Після застосування η-редукції одержимо, що для будь-якого A виконується I = S K A. Таким чином, I = S K A і символ I можна виключити з виразів, побудованих з комбінаторів.
Найбільш часто використовують такі комбінатори:
- тотожність I: I f = f ;
- композитор B: B f g x = f (g x) ;
- дуплікатор W: W f x = f x x ;
- пермутатор C: C f x y = f y x ;
- конектор S: S f g x = f x (g x) ;
- канцелятор K: K x y = x .
Множина комбінаторів, через елементи якої може бути виражений будь-який комбінатор, називається базисом. Мінімальна множина таких комбінаторів називається мінімальним базисом.
Наприклад, для базису {K, S} комбінатори B, W, C мають вигляд:
B = S (R S) K, W = S S (K (S K K)),
C = S (BBS) (KK).
Хоча тут комбінатори представлені як деякі лямбда-терми, існують теорії, де вони є базовим поняттям. Формальний синтаксис у цьому випадку замість лямбда-абстракцій використовує комбінатори. Замість правил α, β і η-редукцій вводяться правила редукції для виразів, які містять комбінатори. Як окрема теорія, теорія комбінаторів має багато аналогій з лямбда-вирахуванням. Зокрема, для неї справедлива теорема Черча-Россера.
Комбінатори мають не тільки теоретичний інтерес. Лямбда-вирахування може розглядатися як проста мова функціонального програмуваня, яка складає ядро реальних мов програмування. Лямбда-вирази можуть бути скомпільовані у код, який складається з комбінаторів. Комбінатори дійсно використовуються як метод реалізації функціональних мов не тільки на рівні програмного, але й на рівні апаратного забезпечення.
5.3 Лямбда-вирахування і мови
Покажемо на простих прикладах, як можна реалізувати базові елементи мов програмування за допомогою лямбда-вирахування.
Значення true і false можна визначити як
true = λx. λy.x, false= λx. λy. y .
Використовуючи це визначення , можна побудувати умовну конструкцію:
if E then E1 else E2 = E E1 E2 .
Дійсно,
if true then E1 else E2 = true E1 E2 =
= (λx.λy.x) E1 E2 = E1 ,
if false then E1 else E2 = false E1 E2 =
= (λx.λy. y) E1 E2 = E2 .
Тепер легко визначити логічні оператори:
not p = if p then false else true ,
p and q = if p then q else false ,
p or q = if p then true else q .
Впорядковану пару можна представити таким чином:
(E1 E2 ) = λf. f E1 E2 ,
а функції для вибору компонент пари:
first (p, q) = (p, q) true, sec (p. q) = (p, q) false .
Дійсно,
first (p, q) = (p, q) true = (λf. f p q) true =
= true p q = (λx.λy.x) p q = p ,
sec (p, q) = (p, q) false = (λf. f p q) false =
= false p q = (λx.λy.y) p q = q .
Натуральне число n можна подати у вигляді:
n = λf. λx.f n x ,
тобто 0 = λf. λx. x, 1 = λf. λx.f x, 2 = λf. λx.f (f x) і т.д. Таке подання називається цифрами за Черчем.
Додаваня і множення можна ввести за допомогою формул:
m + n = λf. λx. m f (n f x),
m * n = λf. λx. m (n f) x .
Перевіримо:
m + n = λf. λx. m f (n f x) =
= λf. λx. (λf. λx. f m x) f (n f x) =
= λf. λx. ( λx. f m x) (n f x) = λf. λx. f m (n f x) =
= λf. λx. f m ((λf. λx. f n x) f x) =
= λf. λx. f m ((λx. f n x) x) = λf. λx. f m ( f n x) =
= λf. λx. f m+ n x ,
m * n = λf. λx. m (n f) x =
= λf. λx. (λf. λx. f m x) (n f) x =
= λf. λx. ( λx. (n f) m x) x =
= λf. λx. (n f) m x = λf. λx. ((λf. λx. f n x) f) m x =
= λf. λx. ( λx. f n x) m x = λf. λx. ( f n ) m x =
= λf. λx. f m n x .
Можна також ввести ряд функцій для роботи з натуральними числами.
Функція перевірки числа на 0:
iszero n = n (λx. false) true .
Це випливає з
iszero 0 = (λf. λx. x) (λx. false) true = true ,
iszero n = (λf. λx. f n+1 x) (λx. false) true =
= (λx. false)n+1 =
= (λx. false) ( (λx. false)n true) = false .
Функцію декремента decr таку, що decr n + 1 = n і decr 0 = 0 , як було показано Кліні, можна ввести за допомогою
decr n = λf. λx. sec ( n (decrn f) (true x)),
decrn = λf. λp.( false, if first p then sec p else f (sec p)).
Важливою характеристикою мови програмування є можливість використовувати рекурсивні функції. Ключовим моментом є існування так званих комбінаторів нерухомої точки.
Замкнений лямбда-терм Y називається комбінатором нерухомої точки, якщо для будь-якого лямбда-терма f виконується f(Y f) = Y f . Таким чином, комбінатор нерухомої точки за заданим термом f повертає нерухому точку f, іншими словами, терм x такий, що f(x) = x. Він визначається таким чином:
Y = λf. (λx. f (x x)) (λx. f (x x)) .
Неважко переконатися, що даний вираз дійсно визначає комбінатор нерухомої точки:
Y f = (λf. (λx. f (x x)) (λx. f (x x))) f =
= (λx. f (x x)) (λx. f (x x)) =
= f ((λx. f (x x)) (λx. f (x x))) =
f (Y f) .
Покажемо, як комбінатор може допомогти у визначенні рекурсивних функцій. Розглянемо, наприклад, функцію факторіала. Ми хочемо визначити функцію fact таку, що
fact (n) = if iszero n then 1 else n*fact (decr n).
Спочатку перетворимо її до такого еквівалентного вигляду:
fact = λn. if iszero n then 1 else n*fact (decr n).
Цей вираз, у свою чергу, еквівалентний
fact = (λf. λn. if iszero n then 1 else n* f (decr n)) fact .
Звідси можна вивести, що fact є нерухомою точкою деякої функції F вигляду:
F = λf. λn. if iszero n then 1 else n* f (decr n).
За допомогою лямбда-вирахування можна також ввести імена для виразів.