SlideShare a Scribd company logo
1 of 14
1
Кубенский А.А. Функциональное программирование.
Глава 4. Основы лямбда-исчисления.
4.2. Рекурсия в лямбда-исчислении
fac = λn.(if (= n 0) 1 (* n (fac (- n 1))))
FB = λf.λn.(if (= n 0) 1 (* n (f (- n 1))))
Найти fac такой, что fac = FB fac
Существует ли функция Y такая, что fac = Y FB ? Y F = F (Y F)
Y-комбинатор; комбинатор фиксированной точки.
Лямбда-выражение для Y-комбинатора: Y = λh.(λx.h (x x))(λx.h (x x))
Y F
(λx.F (x x))(λx.F (x x))
F ((λx.F (x x))(λx.F (x x)))
F (Y F)
Тогда функция fac может быть записана с помощью выражения
Y FB
(λh.(λx.h (x x))(λx.h (x x))) (λf.λn.(if (= n 0) 1 (* n (f (- n 1)))))
Это выражение неприводимо к нормальной форме!
2
Кубенский А.А. Функциональное программирование.
Глава 4. Основы лямбда-исчисления.
Пример работы рекурсии, выраженной с помощью Y-комбинатора
fac 2
(Y FB) 2
FB ((Y FB)) 2 FB = λf.λn.(if (= n 0) 1 (* n (f (- n 1))))
(λn.(if (= n 0) 1 (* n ((Y FB) (- n 1))))) 2
if (= 2 0) 1 (* 2 ((Y FB) (- 2 1)))
* 2 ((Y FB) (- 2 1))
* 2 ((λn.(if (= n 0) 1 (* n ((Y FB) (- n 1))))) (- 2 1))
* 2 (if (= (- 2 1) 0) 1 (* (- 2 1) ((Y FB) (- (- 2 1) 1))))
* 2 (* 1 ((Y FB) (- (- 2 1) 1)))
* 2 (* 1 ((λn.(if (= n 0) 1 (* n ((Y FB) (- n 1))))) (- (- 2 1) 1)))
* 2 (* 1 (if (= 0 0) 1 (* (- (- 2 1) 1) ((Y FB) (- (- (- 2 1) 1) 1)))))
* 2 (* 1 1)
2
3
Кубенский А.А. Функциональное программирование.
Глава 4. Основы лямбда-исчисления.
Взаимно рекурсивные функции
f1 = F1(f1,...,fn)
f2 = F2(f1,...,fn)
fn = Fn(f1,...,fn)
...
T = (f1,...,fn)
TUPLE-n – набор функций кортежирования
T = TUPLE-n f1 ... fn
INDEX – функция индексации
fi = INDEX i T
T = TUPLE-n F1(INDEX 1 T,..., INDEX n T) ... Fn(INDEX 1 T,..., INDEX n T)
Это обычная функция с прямой рекурсией,
которая может быть выражена с помощью Y-комбинатора:
Y (λT.TUPLE-n F1 ... Fn)
а каждая из функций fi получается применением к этому выражению функции индексации:
fi = INDEX i (Y (λT.TUPLE-n F1 ... Fn))
4
Кубенский А.А. Функциональное программирование.
Глава 4. Основы лямбда-исчисления.
4.3. Чистое лямбда-исчисление
Чистое лямбда-исчисление – это исчисление без констант и встроенных функций.
Соответственно, отсутствует и δ-редукция; есть только λ-выражения и β-редукция.
Покажем, что выразительная сила чистого лямбда-исчисления не меньше, чем у
традиционного функционального языка программирования.
1. Функция IF, логические значения и булевы функции.
IF p e1 e2  p e1 e2
TRUE e1 e2  e1
FALSE e1 e2  e2
TRUE = λx.λy.x
FALSE = λx.λy.y
IF = λp.λx.λy.p x y
AND = λp.λq.p q FALSE
OR = λp.λq.p TRUE q
NOT = λp.p FALSE TRUE
5
Кубенский А.А. Функциональное программирование.
Глава 4. Основы лямбда-исчисления.
2. Списки и основные функции обработки списков.
4.3. Чистое лямбда-исчисление (продолжение)
NULL (CONS A B)  FALSE NULL = λt.t (λx.λy.FALSE)
NULL NIL  TRUE NIL = λx.TRUE
проверка: NULL NIL  (λt.t (λx.λy.FALSE))(λx.TRUE)
 (λx.TRUE)(λx.λy.FALSE)  TRUE
CONS A B  λs.s A B CONS = λx.λy.λs.s x y
CAR (λs.s A B)  A
CDR (λs.s A B)  B
CAR = λt.t TRUE
CDR = λt.t FALSE
проверка: CAR (CONS A B)  CAR ((λx.λy.λs.s x y) A B)
 CAR (λs.s A B)  (λt.t TRUE)(λs.s A B)
 (λs.s A B) TRUE  TRUE A B  A
Дополнительные функции обработки списков
JOIN = λp.λq.IF (NULL p) q (CONS (CAR p) (JOIN (CDR p) q))
избавляемся от явной рекурсии с помощью Y-комбинатора
JOIN = Y (λf.λp.λq.IF (NULL p) q (CONS (CAR p) (f (CDR p) q)))
6
Кубенский А.А. Функциональное программирование.
Глава 4. Основы лямбда-исчисления.
3. Целые числа и арифметика.
3а. Представление в виде списков (подсчет элементов списка).
4.3. Чистое лямбда-исчисление (продолжение)
0 = NIL
SUCC = λn.CONS NIL n
PRED = CDR
n = (CONS NIL (CONS NIL (... NIL)))
n разEQ0 = NULL
На базе этих основных функций можно построить всю арифметику.
3б. Функциональное представление (подсчет применений функции).
0 = λf.λx.x n = λf.λx.(f (f (... x)))
n раз
SUCC = λn.λf.λx.(f (n f x))
PLUS = λm.λn.(m SUCC n)
MULT = λm.λn.(m (PLUS n) 0)
EQ0 = λn.(n (λx.FALSE) TRUE)
PRED = λn.λf.λx.(n (λg.λh.(h (g f))) (λu.x) (λu.u))
проверка: PRED 0  λf.λx.(0 (λg.λh.(h (g f))) (λu.x) (λu.u))
 λf.λx.((λu.x) (λu.u))  λf.λx.x  0
Проверим, что PRED 1 = 0:
7
PRED = λn.λf.λx.(n (λg.λh.(h (g f))) (λu.x) (λu.u))
1 = λf.λx.(f x)
Вычитание
PRED 1 = λf.λx.((λf.λx.(f x)) (λg.λh.(h (g f))) (λu.x) (λu.u))
PRED 1 = λf.λx.(((λg.λh.(h (g f))) (λu.x)) (λu.u))
PRED 1 = λf.λx.((λh.(h ((λu.x) f))) (λu.u))
PRED 1 = λf.λx.((λh.(h x)) (λu.u))
PRED 1 = λf.λx.((λu.u) x)
PRED 1 = λf.λx.x = 0
Преимущество функционального представления состоит в том, что основные
арифметические.операции и операции сравнения удается записать без рекурсии.
8
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Глава 5. Системы исполнения функциональных программ
5.1. Интерпретаторы и компиляторы.
Программа
(функция)
Аргументы
Результат
применения
функции
Интерпретатор
Схема интерпретации
Исходная
программа
(функция)
Компилятор
Результирующая
(эквивалентная)
программа
Схема компиляции
В обоих случаях исходная функция служит в качестве входных данных;
в случае компиляции результатом также является функция.
Для получения результата необходима интерпретация
аппаратным или программным интерпретатором.
9
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
5.2. Представление функциональных программ.
Вводим простой функциональный язык – расширенное лямбда-исчисление;
покажем, что все основные конструкции языка типа Haskell могут быть легко
скомпилированы в это расширенное лямбда-исчисление.
1. Константы – целые числа, логические значения. c : 0 25 TRUE
2. Константы – примитивные функции. f : + = IF TUPLE-n INDEX
3. Лямбда-выражения. (λx.e) : λx.+ x x
4. Применение примитивной функции
или лямбда-выражения к аргументу.
(e1 e2) : (λx.+ x x) 2
5. Простой блок. (let x = e1 in e2) :
let f = (λx.+ x x) in (f 2)
6. Рекурсивный блок. (letrec x1 = e1;
x2 = e2;
...
xn = en in e) :
letrec f = λn.IF (= n 0) 1 (* n (f (- n 1))) in (f 5)
Таким образом, в чистое лямбда-исчисление введены константы, функции,
связывание имен со значениями и рекурсия.
10
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
5.2. Представление функциональных программ.
Компиляция с языка Haskell в расширенное лямбда-исчисление.
1. Исключаем все конструкции, связанные с определением и контролем типов:
type, data, ::, class, instance
2. Многие конструкции переводятся (почти) без изменения:
константа: c  c
примитивная функция: f  f
лямбда-выражение: (x->e)  (λx.e'), где e' – результат компиляции e
переменная: x  x
применение функции: (e1 e2)  (e1' e2'); e1+e2  (+ e1' e2')
блоки: (e where f = e1)  (let f = e1' in e')
3. Кортежи переводятся в применения примитивной функции TUPLE-n:
кортеж: (e1, e2, e3)  (TUPLE-3 e1' e2' e3')
4. Применение конструкторов переводится в применение примитивной функции TUPLE-n,
первым аргументом которого служит номер конструктора в определении типа:
например: [3]  3 : []  (TUPLE-3 1 3 (TUPLE-1 0))
5. Многие конструкции, такие как фильтры, арифметические прогрессии и т.п. переводятся
в вызовы соответствующих примитивных функций.
11
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Компиляция с языка Haskell в расширенное лямбда-исчисление.
6. Определения функций, включающие образцы и условия, сначала переводятся в
лямбда-выражения, содержащие конструкцию case в определяющем выражении.
например: assoc x ((y,e):lst) | x == y = e
| otherwise = assoc x lst
assoc x [] = []
переходит в: assoc = a1 -> a2 -> case (a1, a2) of
(x, ((y,e):lst)) | x == y -> e
| otherwise -> assoc x lst
(_, []) -> []
Конструкция case затем транслируется в расширенное лямбда-исчисление (далее).
7. Программный модуль (серия определений) транслируется в заголовок блока letrec.
name_1 = expr_1
name_2 = expr_2
...
name_k = expr_k

letrec name_1 = expr_1';
name_2 = expr_2';
...
name_k = expr_k' in
Перед исполнением программы вычисляемое выражение
компилируется и помещается в блок letrec после in.
12
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Компиляция case-выражения
case param of
pattern_1 | cond_11 -> expr_11
| cond_12 -> expr_12 ...
pattern_2 | cond_21 -> expr_21 ...
...
pattern_k | cond_k1 -> expr_k1 ...
letrec f1 = λa.IF (образец_1)
let (связывание_1) in
IF cond_11' expr_11'
IF cond_12' expr_12' ...
(f2 a)
(f2 a)
f2 = λa.IF (образец_2)
let (связывание_2) in
IF cond_21' expr_21'
IF cond_22' expr_22' ...
(f3 a)
(f3 a)
...
fk = λa.IF (образец_k) ...
error
error
in f1 param'

13
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Компиляция сопоставления с образцом и связывания
case arg@(x, y) of
([], (e:_)) -> expr
Аргумент arg, удовлетворяющий образцу, должен иметь вид:
( [], ( (:) e _ ))
(TUPLE-2 (TUPLE-1 0) (TUPLE-3 1 e foo))
(AND (EQ (INDEX 1 (INDEX 1 arg)) 0) (EQ (INDEX 1 (INDEX 2 arg)) 1))
arg[1,1] == 0 && arg[2,1] == 1
Возможно также сопоставление с константой:
case arg of
[25] -> expr
((:) 25 [])
arg[1] == 1 && arg[2] == 25 && arg[3,1] == 0
Связывание:
x = arg[1]; y = arg[2]; e = arg[2,2]
14
Кубенский А.А. Функциональное программирование.
Глава 5. Системы исполнения функциональных программ.
Представление программ расширенного лямбда-исчисления
data Expr = Integral Integer | Logical Bool -- константы
| Function String -- примитивные функции
| Variable String -- переменные
| Lambda String Expr -- лямбда-выражение
| Application Expr Expr -- применение функции
| Let String Expr Expr -- простой блок
| Letrec [(String, Expr)] Expr -- рекурсивный блок
например: let plus = (λx.λy.x+y) in (plus 1 2)
будет представлено в виде:
(Let "plus"
(Lambda "x" (Lambda "y"
(Application (Application (Function "+") (Variable "x"))
(Variable "y"))))
(Application (Application (Variable "plus") (Integral 1)) (Integral 2))
)

More Related Content

What's hot

Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияYandex
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Stfalcon Meetups
 
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Nikolay Grebenshikov
 
алгоритмы stl
алгоритмы stlалгоритмы stl
алгоритмы stlmcroitor
 
возростание и убывание функции
возростание и убывание функциивозростание и убывание функции
возростание и убывание функцииАня Иванова
 
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...Nikolay Grebenshikov
 
Functional Programing
Functional ProgramingFunctional Programing
Functional ProgramingMax Arshinov
 
стандартная библиотека с++: введение
стандартная библиотека с++: введениестандартная библиотека с++: введение
стандартная библиотека с++: введениеmcroitor
 
особенности программирования на с++
особенности программирования на с++особенности программирования на с++
особенности программирования на с++mcroitor
 
A System of Deductive Verification of Predicate Programs
A System of Deductive Verification of Predicate ProgramsA System of Deductive Verification of Predicate Programs
A System of Deductive Verification of Predicate ProgramsIosif Itkin
 
лабораторная работа №5
лабораторная работа №5лабораторная работа №5
лабораторная работа №5Zhanna Kazakova
 
Cpp/cli types
Cpp/cli typesCpp/cli types
Cpp/cli typesmcroitor
 
"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24
"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24
"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24MoscowJS
 
C# Desktop. Занятие 03.
C# Desktop. Занятие 03.C# Desktop. Занятие 03.
C# Desktop. Занятие 03.Igor Shkulipa
 
4.2 Перегрузка
4.2 Перегрузка4.2 Перегрузка
4.2 ПерегрузкаDEVTYPE
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Alexey Paznikov
 

What's hot (20)

Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8
 
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
Лекция №3. Свойства и моделирование стандартных схем программ. Предмет "Теори...
 
алгоритмы stl
алгоритмы stlалгоритмы stl
алгоритмы stl
 
возростание и убывание функции
возростание и убывание функциивозростание и убывание функции
возростание и убывание функции
 
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
Лекция №2. Алгоритмические проблемы. Стандартные схемы программ. Предмет "Тео...
 
Functional Programing
Functional ProgramingFunctional Programing
Functional Programing
 
стандартная библиотека с++: введение
стандартная библиотека с++: введениестандартная библиотека с++: введение
стандартная библиотека с++: введение
 
Урок 1. Что такое функциональное программирование
Урок 1. Что такое функциональное программированиеУрок 1. Что такое функциональное программирование
Урок 1. Что такое функциональное программирование
 
особенности программирования на с++
особенности программирования на с++особенности программирования на с++
особенности программирования на с++
 
A System of Deductive Verification of Predicate Programs
A System of Deductive Verification of Predicate ProgramsA System of Deductive Verification of Predicate Programs
A System of Deductive Verification of Predicate Programs
 
Синтез функциональных программ при помощи метода дедуктивных таблиц
Синтез функциональных программ при помощи метода дедуктивных таблицСинтез функциональных программ при помощи метода дедуктивных таблиц
Синтез функциональных программ при помощи метода дедуктивных таблиц
 
лабораторная работа №5
лабораторная работа №5лабораторная работа №5
лабораторная работа №5
 
10474
1047410474
10474
 
Cpp/cli types
Cpp/cli typesCpp/cli types
Cpp/cli types
 
"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24
"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24
"Как написать компилятор за 15 минут", Андрей Гершун, MoscowJS 24
 
C# Desktop. Занятие 03.
C# Desktop. Занятие 03.C# Desktop. Занятие 03.
C# Desktop. Занятие 03.
 
4.2 Перегрузка
4.2 Перегрузка4.2 Перегрузка
4.2 Перегрузка
 
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...
 
вычислительная практика
вычислительная практикавычислительная практика
вычислительная практика
 

Similar to Урок 6. Чистое лямбда-исчисление.

Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программированияAlex.Kolonitsky
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
 
Haskell Type System with Dzmitry Ivashnev.
Haskell Type System with Dzmitry Ivashnev.Haskell Type System with Dzmitry Ivashnev.
Haskell Type System with Dzmitry Ivashnev.Sergey Tihon
 
Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Fwdays
 
Использование GNU OCTAVE для инженерных и математических расчетов
Использование GNU OCTAVE для инженерных и математических расчетовИспользование GNU OCTAVE для инженерных и математических расчетов
Использование GNU OCTAVE для инженерных и математических расчетовТранслируем.бел
 
Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8Technopark
 
Лекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмовЛекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмовMikhail Kurnosov
 
Интерпретирование языков с помощью Free-монад
Интерпретирование языков с помощью Free-монадИнтерпретирование языков с помощью Free-монад
Интерпретирование языков с помощью Free-монадZheka Kozlov
 
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...Tech Talks @NSU
 

Similar to Урок 6. Чистое лямбда-исчисление. (20)

Урок 8. Введение в редукцию графов
Урок 8. Введение в редукцию графовУрок 8. Введение в редукцию графов
Урок 8. Введение в редукцию графов
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
 
Функциональное программирование.Списки. Функции высших порядков
Функциональное программирование.Списки. Функции высших порядковФункциональное программирование.Списки. Функции высших порядков
Функциональное программирование.Списки. Функции высших порядков
 
Урок 7. Интерпретация и компиляция функциональных программ.
Урок 7. Интерпретация и компиляция функциональных программ.Урок 7. Интерпретация и компиляция функциональных программ.
Урок 7. Интерпретация и компиляция функциональных программ.
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
Haskell Type System with Dzmitry Ivashnev.
Haskell Type System with Dzmitry Ivashnev.Haskell Type System with Dzmitry Ivashnev.
Haskell Type System with Dzmitry Ivashnev.
 
Урок 3. Карринг и ленивые вычисления.
Урок 3. Карринг и ленивые вычисления.Урок 3. Карринг и ленивые вычисления.
Урок 3. Карринг и ленивые вычисления.
 
Основы Python. Функции
Основы Python. ФункцииОсновы Python. Функции
Основы Python. Функции
 
Урок 4. "Завязывание узлов". Классы
Урок 4. "Завязывание узлов". КлассыУрок 4. "Завязывание узлов". Классы
Урок 4. "Завязывание узлов". Классы
 
Scala #3
Scala #3Scala #3
Scala #3
 
Lisp8
Lisp8Lisp8
Lisp8
 
Lisp8
Lisp8Lisp8
Lisp8
 
Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"Николай Паламарчук "Functional Programming basics for PHP developers"
Николай Паламарчук "Functional Programming basics for PHP developers"
 
Использование GNU OCTAVE для инженерных и математических расчетов
Использование GNU OCTAVE для инженерных и математических расчетовИспользование GNU OCTAVE для инженерных и математических расчетов
Использование GNU OCTAVE для инженерных и математических расчетов
 
Clojure #1
Clojure #1Clojure #1
Clojure #1
 
Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8Алгоритмы и структуры данных осень 2013 лекция 8
Алгоритмы и структуры данных осень 2013 лекция 8
 
Лекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмовЛекция 11: Методы разработки алгоритмов
Лекция 11: Методы разработки алгоритмов
 
Интерпретирование языков с помощью Free-монад
Интерпретирование языков с помощью Free-монадИнтерпретирование языков с помощью Free-монад
Интерпретирование языков с помощью Free-монад
 
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
Tech Talks @NSU: Теоретические основы программирования: проекции Футамуры-Тур...
 
Подпрограммы
ПодпрограммыПодпрограммы
Подпрограммы
 

Урок 6. Чистое лямбда-исчисление.

  • 1. 1 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления. 4.2. Рекурсия в лямбда-исчислении fac = λn.(if (= n 0) 1 (* n (fac (- n 1)))) FB = λf.λn.(if (= n 0) 1 (* n (f (- n 1)))) Найти fac такой, что fac = FB fac Существует ли функция Y такая, что fac = Y FB ? Y F = F (Y F) Y-комбинатор; комбинатор фиксированной точки. Лямбда-выражение для Y-комбинатора: Y = λh.(λx.h (x x))(λx.h (x x)) Y F (λx.F (x x))(λx.F (x x)) F ((λx.F (x x))(λx.F (x x))) F (Y F) Тогда функция fac может быть записана с помощью выражения Y FB (λh.(λx.h (x x))(λx.h (x x))) (λf.λn.(if (= n 0) 1 (* n (f (- n 1))))) Это выражение неприводимо к нормальной форме!
  • 2. 2 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления. Пример работы рекурсии, выраженной с помощью Y-комбинатора fac 2 (Y FB) 2 FB ((Y FB)) 2 FB = λf.λn.(if (= n 0) 1 (* n (f (- n 1)))) (λn.(if (= n 0) 1 (* n ((Y FB) (- n 1))))) 2 if (= 2 0) 1 (* 2 ((Y FB) (- 2 1))) * 2 ((Y FB) (- 2 1)) * 2 ((λn.(if (= n 0) 1 (* n ((Y FB) (- n 1))))) (- 2 1)) * 2 (if (= (- 2 1) 0) 1 (* (- 2 1) ((Y FB) (- (- 2 1) 1)))) * 2 (* 1 ((Y FB) (- (- 2 1) 1))) * 2 (* 1 ((λn.(if (= n 0) 1 (* n ((Y FB) (- n 1))))) (- (- 2 1) 1))) * 2 (* 1 (if (= 0 0) 1 (* (- (- 2 1) 1) ((Y FB) (- (- (- 2 1) 1) 1))))) * 2 (* 1 1) 2
  • 3. 3 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления. Взаимно рекурсивные функции f1 = F1(f1,...,fn) f2 = F2(f1,...,fn) fn = Fn(f1,...,fn) ... T = (f1,...,fn) TUPLE-n – набор функций кортежирования T = TUPLE-n f1 ... fn INDEX – функция индексации fi = INDEX i T T = TUPLE-n F1(INDEX 1 T,..., INDEX n T) ... Fn(INDEX 1 T,..., INDEX n T) Это обычная функция с прямой рекурсией, которая может быть выражена с помощью Y-комбинатора: Y (λT.TUPLE-n F1 ... Fn) а каждая из функций fi получается применением к этому выражению функции индексации: fi = INDEX i (Y (λT.TUPLE-n F1 ... Fn))
  • 4. 4 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления. 4.3. Чистое лямбда-исчисление Чистое лямбда-исчисление – это исчисление без констант и встроенных функций. Соответственно, отсутствует и δ-редукция; есть только λ-выражения и β-редукция. Покажем, что выразительная сила чистого лямбда-исчисления не меньше, чем у традиционного функционального языка программирования. 1. Функция IF, логические значения и булевы функции. IF p e1 e2  p e1 e2 TRUE e1 e2  e1 FALSE e1 e2  e2 TRUE = λx.λy.x FALSE = λx.λy.y IF = λp.λx.λy.p x y AND = λp.λq.p q FALSE OR = λp.λq.p TRUE q NOT = λp.p FALSE TRUE
  • 5. 5 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления. 2. Списки и основные функции обработки списков. 4.3. Чистое лямбда-исчисление (продолжение) NULL (CONS A B)  FALSE NULL = λt.t (λx.λy.FALSE) NULL NIL  TRUE NIL = λx.TRUE проверка: NULL NIL  (λt.t (λx.λy.FALSE))(λx.TRUE)  (λx.TRUE)(λx.λy.FALSE)  TRUE CONS A B  λs.s A B CONS = λx.λy.λs.s x y CAR (λs.s A B)  A CDR (λs.s A B)  B CAR = λt.t TRUE CDR = λt.t FALSE проверка: CAR (CONS A B)  CAR ((λx.λy.λs.s x y) A B)  CAR (λs.s A B)  (λt.t TRUE)(λs.s A B)  (λs.s A B) TRUE  TRUE A B  A Дополнительные функции обработки списков JOIN = λp.λq.IF (NULL p) q (CONS (CAR p) (JOIN (CDR p) q)) избавляемся от явной рекурсии с помощью Y-комбинатора JOIN = Y (λf.λp.λq.IF (NULL p) q (CONS (CAR p) (f (CDR p) q)))
  • 6. 6 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления. 3. Целые числа и арифметика. 3а. Представление в виде списков (подсчет элементов списка). 4.3. Чистое лямбда-исчисление (продолжение) 0 = NIL SUCC = λn.CONS NIL n PRED = CDR n = (CONS NIL (CONS NIL (... NIL))) n разEQ0 = NULL На базе этих основных функций можно построить всю арифметику. 3б. Функциональное представление (подсчет применений функции). 0 = λf.λx.x n = λf.λx.(f (f (... x))) n раз SUCC = λn.λf.λx.(f (n f x)) PLUS = λm.λn.(m SUCC n) MULT = λm.λn.(m (PLUS n) 0) EQ0 = λn.(n (λx.FALSE) TRUE) PRED = λn.λf.λx.(n (λg.λh.(h (g f))) (λu.x) (λu.u)) проверка: PRED 0  λf.λx.(0 (λg.λh.(h (g f))) (λu.x) (λu.u))  λf.λx.((λu.x) (λu.u))  λf.λx.x  0 Проверим, что PRED 1 = 0:
  • 7. 7 PRED = λn.λf.λx.(n (λg.λh.(h (g f))) (λu.x) (λu.u)) 1 = λf.λx.(f x) Вычитание PRED 1 = λf.λx.((λf.λx.(f x)) (λg.λh.(h (g f))) (λu.x) (λu.u)) PRED 1 = λf.λx.(((λg.λh.(h (g f))) (λu.x)) (λu.u)) PRED 1 = λf.λx.((λh.(h ((λu.x) f))) (λu.u)) PRED 1 = λf.λx.((λh.(h x)) (λu.u)) PRED 1 = λf.λx.((λu.u) x) PRED 1 = λf.λx.x = 0 Преимущество функционального представления состоит в том, что основные арифметические.операции и операции сравнения удается записать без рекурсии.
  • 8. 8 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Глава 5. Системы исполнения функциональных программ 5.1. Интерпретаторы и компиляторы. Программа (функция) Аргументы Результат применения функции Интерпретатор Схема интерпретации Исходная программа (функция) Компилятор Результирующая (эквивалентная) программа Схема компиляции В обоих случаях исходная функция служит в качестве входных данных; в случае компиляции результатом также является функция. Для получения результата необходима интерпретация аппаратным или программным интерпретатором.
  • 9. 9 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. 5.2. Представление функциональных программ. Вводим простой функциональный язык – расширенное лямбда-исчисление; покажем, что все основные конструкции языка типа Haskell могут быть легко скомпилированы в это расширенное лямбда-исчисление. 1. Константы – целые числа, логические значения. c : 0 25 TRUE 2. Константы – примитивные функции. f : + = IF TUPLE-n INDEX 3. Лямбда-выражения. (λx.e) : λx.+ x x 4. Применение примитивной функции или лямбда-выражения к аргументу. (e1 e2) : (λx.+ x x) 2 5. Простой блок. (let x = e1 in e2) : let f = (λx.+ x x) in (f 2) 6. Рекурсивный блок. (letrec x1 = e1; x2 = e2; ... xn = en in e) : letrec f = λn.IF (= n 0) 1 (* n (f (- n 1))) in (f 5) Таким образом, в чистое лямбда-исчисление введены константы, функции, связывание имен со значениями и рекурсия.
  • 10. 10 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. 5.2. Представление функциональных программ. Компиляция с языка Haskell в расширенное лямбда-исчисление. 1. Исключаем все конструкции, связанные с определением и контролем типов: type, data, ::, class, instance 2. Многие конструкции переводятся (почти) без изменения: константа: c  c примитивная функция: f  f лямбда-выражение: (x->e)  (λx.e'), где e' – результат компиляции e переменная: x  x применение функции: (e1 e2)  (e1' e2'); e1+e2  (+ e1' e2') блоки: (e where f = e1)  (let f = e1' in e') 3. Кортежи переводятся в применения примитивной функции TUPLE-n: кортеж: (e1, e2, e3)  (TUPLE-3 e1' e2' e3') 4. Применение конструкторов переводится в применение примитивной функции TUPLE-n, первым аргументом которого служит номер конструктора в определении типа: например: [3]  3 : []  (TUPLE-3 1 3 (TUPLE-1 0)) 5. Многие конструкции, такие как фильтры, арифметические прогрессии и т.п. переводятся в вызовы соответствующих примитивных функций.
  • 11. 11 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Компиляция с языка Haskell в расширенное лямбда-исчисление. 6. Определения функций, включающие образцы и условия, сначала переводятся в лямбда-выражения, содержащие конструкцию case в определяющем выражении. например: assoc x ((y,e):lst) | x == y = e | otherwise = assoc x lst assoc x [] = [] переходит в: assoc = a1 -> a2 -> case (a1, a2) of (x, ((y,e):lst)) | x == y -> e | otherwise -> assoc x lst (_, []) -> [] Конструкция case затем транслируется в расширенное лямбда-исчисление (далее). 7. Программный модуль (серия определений) транслируется в заголовок блока letrec. name_1 = expr_1 name_2 = expr_2 ... name_k = expr_k  letrec name_1 = expr_1'; name_2 = expr_2'; ... name_k = expr_k' in Перед исполнением программы вычисляемое выражение компилируется и помещается в блок letrec после in.
  • 12. 12 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Компиляция case-выражения case param of pattern_1 | cond_11 -> expr_11 | cond_12 -> expr_12 ... pattern_2 | cond_21 -> expr_21 ... ... pattern_k | cond_k1 -> expr_k1 ... letrec f1 = λa.IF (образец_1) let (связывание_1) in IF cond_11' expr_11' IF cond_12' expr_12' ... (f2 a) (f2 a) f2 = λa.IF (образец_2) let (связывание_2) in IF cond_21' expr_21' IF cond_22' expr_22' ... (f3 a) (f3 a) ... fk = λa.IF (образец_k) ... error error in f1 param' 
  • 13. 13 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Компиляция сопоставления с образцом и связывания case arg@(x, y) of ([], (e:_)) -> expr Аргумент arg, удовлетворяющий образцу, должен иметь вид: ( [], ( (:) e _ )) (TUPLE-2 (TUPLE-1 0) (TUPLE-3 1 e foo)) (AND (EQ (INDEX 1 (INDEX 1 arg)) 0) (EQ (INDEX 1 (INDEX 2 arg)) 1)) arg[1,1] == 0 && arg[2,1] == 1 Возможно также сопоставление с константой: case arg of [25] -> expr ((:) 25 []) arg[1] == 1 && arg[2] == 25 && arg[3,1] == 0 Связывание: x = arg[1]; y = arg[2]; e = arg[2,2]
  • 14. 14 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Представление программ расширенного лямбда-исчисления data Expr = Integral Integer | Logical Bool -- константы | Function String -- примитивные функции | Variable String -- переменные | Lambda String Expr -- лямбда-выражение | Application Expr Expr -- применение функции | Let String Expr Expr -- простой блок | Letrec [(String, Expr)] Expr -- рекурсивный блок например: let plus = (λx.λy.x+y) in (plus 1 2) будет представлено в виде: (Let "plus" (Lambda "x" (Lambda "y" (Application (Application (Function "+") (Variable "x")) (Variable "y")))) (Application (Application (Variable "plus") (Integral 1)) (Integral 2)) )