- •Содержание
- •1. Введение в функции
- •1.1. Чистые функции
- •1.2. Функциональность
- •2. Введение в функциональное программирование
- •2.1. О языке Лисп
- •2.2. Примеры программ
- •2.3. Символьная обработка
- •2.4. Особенности Лиспа
- •3. Основы языка лисп
- •3.1. Символы и списки
- •3. 2. Понятие функции
- •3.3. Базовые функции
- •3.4. Имя и значение символа
- •4. Определение функций
- •5. Математические основы: -исчисление
- •5. 1. Введение в синтаксис
- •Определение -термов
- •5.2. Вычисление -выражений
- •5.3. Порядок редукций и нормальные формы
- •5.4. Рекурсивные выражения
- •5.5. Чистое -исчисление
- •5.6. Ламбда-абстракции в Лиспе
- •6. Внутреннее представление списков
- •7. Рекурсия
- •7.1. Простая рекурсия
- •7.2. Другие формы рекурсии
- •8. Функции более высокого порядка
- •8.1. Функционалы
- •8.2. Способы композиции функций
- •8.3. Замыкания
- •8.4. Абстрактный подход
5.4. Рекурсивные выражения
Проблема рекурсивных функций в -исчислении, где функции не имеют имени: необходимо придумать метод, позволяющий функциям вызывать себя не по имени, а каким-то другим образом.
Представим рекурсивную функцию как функцию, имеющуюе себя в качестве аргумента. В этом случае функция может оказаться связанной с одной из её собственных переменных и будет, таким образом, содержать в своем теле ссылки на самое себя.
Рассмотрим, например, рекурсивную функцию sum, определенную на языке Лисп следующим образом:
(defun sum (n)
(if (= n 0) 0 (+ n (sum (1- n))))
)
Это выражение может быть представлено в виде -абстракции, имеющей дополнительный параметр, который при применении этой абстракции связывается с самой функцией. Мы запишем эту промежуточную версию функции sum:
sum = s . n . IF (= 0 n) 0 (+ n (s (1- n)))
Все, что нам осталось сделать теперь, - это связать переменную s со значением функции sum, которую пытаемся определить. Это можно сделать, использовав специальную функцию, называемую Y-комбинатором, которая удовлетворяет следующему уравнению:
Y f = f (Y f)
Y также известен как комбинатор неподвижной точки. “Неподвижная точка” функции f - это выражение, которое не изменяется при применении к нему функции f. (Заметим, что функция может иметь несколько неподвижных точек. Например, функция тождества x . x, имеет бесконечное их число.) Выражение Y f дает наименьшую неподвижную точку функции f .
Y sum
= Y(s . n . IF (= 0 n) 0 (+ n (s (1- n))))
(s . n . IF (= 0 n) 0 (+ n (s (1- n)))) (Y sum)
n . IF (= 0 n) 0 (+ n ((Y sum) (1- n)))
n . IF (= 0 n) 0
(+ n ((m . IF (= 0 m) 0 (+ m ((Y sum) (1- m))))
(1- n))))
Данное выражение ведет себя точно так же, как исходное рекурсивное определение sum. Внутреннее вхождение Y sum конструирует копию исходной функции sum, помещая само себя (т. е. Y sum) вместо s в тело копии.
Таким образом, функция sum выражается в -исчислении в виде
Y(s . n . IF (= 0 n) 0 (+ n (s (1- n))))
Проверим:
(Y(s . n . IF (= 0 n) 0 (+ n (s (1- n))))) 1
n . IF (= 0 n) 0 (+ n ((Y(s . n . IF (= 0 n) 0 (+ n (s (1- n)))))
(1- n))) 1
IF (= 0 1) 0 (+ 1 ((Y(s . n . IF (= 0 n) 0 (+ n (s (1- n)))))
(1- 1)))
(+ 1 ((Y(s . n . IF (= 0 n) 0 (+ n (s (1- n))))) 0))
(+ 1 (n . IF (= 0 n) 0
(+ n ((Y(s . n . ...))))) 0)
(+ 1 (IF (= 0 0) 0 (+ 0 ((Y (s . n . ...))))))
(+ 1 0)
1
В общем случае рекурсивная функция f с телом, задаваемым выражением E, записывается в -исчислении в виде Y (f . E).
Определение Y
Y = h . (x . h ( x x)) (x . h (x x))
Проверим:
Yf=
(h . (x . h ( x x)) (x . h (x x))) f
(x . f ( x x)) (x . f (x x))
f ((x . f (x x)) (x . f (x x)) )
f (Y f)
5.5. Чистое -исчисление
Удалив константы и -правила, мы получаем чистое -исчисление. В нем можно выразить любые константы и функции.
Булевы константы и условное выражение
TRUE = x . y . x TRUE A B A
FALSE = x . y . y FALSE A B B
IF = p . q . r . p q r
IF TRUE A B =
(p . q . r . p q r) ( x . y . x) A B
(q . r . ( x . y . x) q r ) A B
(q . r . (y . q) r ) A B
(q . r . q ) A B
(r . A ) B
A
Конструктор списков и функции-селекторы. Определим список как выражение CONS A B, где
CONS = h . t . s s h t
FIRST = L . L TRUE
REST = L . L FALSE
FIRST ( CONS A B) =
(L . L TRUE) ( CONS A B)
( CONS A B) TRUE
((h . t . s s h t) A B ) TRUE
((t . s s A t) B ) TRUE
(s s A B) TRUE
TRUE A B
= (x . y . x) A B
y . A B
A
Натуральные числа. Натуральное число n часто представляется термом n -кратной композиции (обозначение x^n(y) служит сокращением для x(x(...(xy)...)), x повторяется раз).
Для каждого натурального числа n положим
<0> = x . y . y, <n> = x . y . x^n (y)
Тогда сложение чисел определяется ламбда-выражением
+ x y = p . q . x p (y p q)
Проверим, что определение удачно.
+ 1 1 = p . q . <1> p (<1> p q)
= p . (q . ((x . y . x y) p ((x . y . x y) p q)))
p . (q . ((x . y . x y) p p q))
p . (q . (p p q))
= <2>