осень 2026
осень 2026
Летучка 3 · 7 минут · Ваше ФИ: ____________________
Программа — это дерево. Попробуем приписать каждой вершине метку-тип, двигаясь от листьев к корню.
if (x < 2) (x + 1) 0
Листья. Константа знает свою метку сама; про переменную x нужно знать заранее — пусть x : \mathrm{Int}.
if (x < 2) (x + 1) 0
Правило для <: если оба поддерева помечены \mathrm{Int}, вершина получает метку \mathrm{Bool}. Правило для +: оба поддерева \mathrm{Int} — метка \mathrm{Int}.
if (x < 2) (x + 1) 0
Правило для if: условие помечено \mathrm{Bool}, ветки помечены одинаково — вершина получает метку веток. Помечено всё дерево: программа «хорошая».
if (x < 2) (x + 1) 0
А если сравнить x с переменной b, про которую дано b : \mathrm{Bool}? Правило для < не срабатывает, метки нет, выше идти не с чем: программа отвергнута до запуска.
if (x < b) (x + 1) 0
Здесь f помечена \mathrm{Int}\to\mathrm{Int}, а вся программа — (\mathrm{Int}\to\mathrm{Int})\to\mathrm{Int}.
λf. f (f 1)
Стрелка — узел с двумя поддеревьями: слева тип аргумента, справа тип результата. Листья — константы \mathrm{Int}, \mathrm{Bool} и типовые переменные \alpha, \beta.
λf. f (f 1)
Тип всей программы — тоже дерево: (\mathrm{Int}\to\mathrm{Int})\to\mathrm{Int}. Скобки в записи — это форма дерева: слева поддерево \mathrm{Int}\to\mathrm{Int}, программа принимает функцию.
λf. f (f 1)
Остальные метки — деревья из одного листа. Итог: анализ типов аннотирует дерево программы деревьями типов; осталось договориться, по каким правилам метка вершины получается из меток поддеревьев.
λf. f (f 1)
Без скобок стрелка группируется вправо: \lambda x\,y.\,x \mathrel{\mathtt{+}} y : \mathrm{Int}\to\mathrm{Int}\to\mathrm{Int} — это \mathrm{Int}\to(\mathrm{Int}\to\mathrm{Int}), функция, возвращающая функцию. У нашей программы скобки слева — другое дерево.
λf. f (f 1)
Синтаксис \lambda_\to — как в лекции + наше расширение
Типы: \quad T ::= \alpha \ \mid\ T \to T \ \mid\ \mathrm{Int} \ \mid\ \mathrm{Bool}
Термы: \quad M ::= x \ \mid\ M\ M \ \mid\ \lambda x.\,M \qquad по Чёрчу — \lambda x^T.\,M
\phantom{M ::=} \mid\ n \ \mid\ M \mathrel{\mathtt{+}} M \ \mid\ M \mathrel{\mathtt{-}} M \ \mid\ M \mathrel{\mathtt{*}} M, где n \in \mathbb{N} = \{\mathtt{0}, \mathtt{1}, \mathtt{2}, \ldots\}
\phantom{M ::=} \mid\ b \ \mid\ M \mathrel{\mathtt{<}} M \ \mid\ M \mathrel{\mathtt{==}} M \ \mid\ \mathtt{if}\ M\ M\ M, где b \in \mathbb{B} = \{\mathtt{true}, \mathtt{false}\}
Расширение — числа и були встроены в язык как новые формы терма. Это не \mathbf{plus} и \mathbf{true} из практики 1: раскрыть их в \lambda-терм нельзя; \mathtt{2} \mathrel{\mathtt{+}} \mathtt{3} \rightsquigarrow_{+} \mathtt{5} происходит за один шаг
Припишите тип терму \lambda x.\,x \mathrel{\mathtt{+}} \mathtt{1}
Функция: ?\to\ ?. Складывать можно только числа — x : \mathrm{Int}, сумма — число. Ответ: \mathrm{Int}\to\mathrm{Int}
Припишите тип терму \lambda b.\,\mathtt{if}\ b\ \mathtt{0}\ \mathtt{1}
b — условие: b : \mathrm{Bool}; обе ветки \mathrm{Int}, значит и всё \mathtt{if} — \mathrm{Int}. Ответ: \mathrm{Bool}\to\mathrm{Int}
Припишите тип терму \mathtt{true} \mathrel{\mathtt{+}} \mathtt{1}
Типа нет: слагаемые обязаны быть числами, а \mathtt{true} : \mathrm{Bool}
Найдите наиболее общий тип терма \lambda x\,y.\,x
Типы аргументов в терме не записаны, а тело их никак не ограничивает — выбираем различные буквы: \alpha\to\beta\to\ ?. Результат — первый аргумент. Ответ: \alpha\to\beta\to\alpha
Найдите наиболее общий тип терма \lambda x\,y\,f.\,f\ x\ y
f в теле принимает два аргумента — x и y, на них ограничений нет: \alpha\to\beta\to(\alpha\to\beta\to\ ?)\to\ ?. Результат f ничем не ограничен — берём свежую букву. Ответ: \alpha\to\beta\to(\alpha\to\beta\to\gamma)\to\gamma
Припишите тип терму \lambda x^\alpha\,f^{\alpha \to \beta}.\,f\ x — здесь типы аргументов уже подписаны
Видим абстракцию — пишем стрелку \alpha\to\ ? и типизируем тело, зная x^\alpha. Тело — тоже функция: \alpha\to((\alpha\to\beta)\to\ ?). Внутри знаем x^\alpha и f^{\alpha\to\beta}: тип x совпадает с типом аргумента f, значит f\ x : \beta. Ответ: \alpha\to(\alpha\to\beta)\to\beta
Найдите наиболее общий тип терма \lambda f\,x.\,f\ (f\ x)
f применяют, значит f : \alpha\to\beta. Результат f\ x снова отдают в f, значит \beta и \alpha — один тип; x — того же типа. Ответ: (\alpha\to\alpha)\to\alpha\to\alpha
А какой тип у \lambda x.\,x\ x?
Никакого. x применяют — значит x : \alpha\to\beta; аргументом стоит тот же x — значит x : \alpha. Получается \alpha \equiv \alpha\to\beta: тип должен быть собственной частью, а у конечного дерева так не бывает.
Населите тип (\beta\to\gamma)\to(\alpha\to\beta)\to\alpha\to\gamma — то есть постройте терм такого типа
(а) \lambda x.\,x : \alpha\to\alpha. Какие из типов тоже подходят этому терму: \ \mathrm{Int}\to\mathrm{Int}, \quad (\beta\to\gamma)\to(\beta\to\gamma), \quad \mathrm{Int}\to\mathrm{Bool}, \quad \alpha\to\beta?
(б) \lambda x.\,x \mathrel{\mathtt{+}} \mathtt{1} : \mathrm{Int}\to\mathrm{Int}. А тип \alpha\to\alpha ему подходит?
(в) \lambda x\,y.\,x имеет типы \alpha\to\alpha\to\alpha и \alpha\to\beta\to\alpha. Который из них главнее?
Пример на Си
Контекст типизации в каждой из точек:
0. a^{\mathrm{int}},\ i^{\mathrm{char}}
1. a^{\mathrm{int}},\ c^{\mathrm{int}},\ i^{\mathrm{int}}
2. a^{\mathrm{int}},\ c^{\mathrm{int}},\ i^{\mathrm{int}},\ r^{\mathrm{long}}
3. a^{\mathrm{int}},\ c^{\mathrm{int}},\ i^{\mathrm{char}}
+ Глобальные определения: <, +, *… — это наши константы
В чистом лямбда-исчислении имена вводятся с помощью абстракции: \lambda f^A\,g^B\,x^C.\,f\ (g\ x) по Чёрчу.
Контекст типизации для каждой вершины:
(0) пустой
(1) f^A
(2) f^A,\ g^B
(∗) f^A,\ g^B,\ x^C — и во всех вершинах ниже
Вспомните правила с лекции: по одному на каждый вид терма.
Правила с лекции
\dfrac{x^A \in \Gamma}{\Gamma \vdash x : A}\ {\scriptstyle (\text{акс})} \dfrac{\Gamma \vdash M : A \to B \quad \Gamma \vdash N : A}{\Gamma \vdash M\ N : B}\ {\scriptstyle (\to E)} \dfrac{\Gamma,\ x^A \vdash M : B}{\Gamma \vdash \lambda x.\,M : A \to B}\ {\scriptstyle (\to I)}
Константы — тоже вершины дерева, и у каждого вида своё правило: литералы и \mathtt{true}/\mathtt{false} — листья, операторы и \mathtt{if} — вершины с поддеревьями.
Натуральные числа
\dfrac{n \in \{\mathtt{0}, \mathtt{1}, \mathtt{2}, \ldots\}}{\Gamma \vdash n : \mathrm{Int}}\ {\scriptstyle (\text{нат})} \dfrac{\Gamma \vdash M : \mathrm{Int} \quad \Gamma \vdash N : \mathrm{Int}}{\Gamma \vdash M \mathrel{\mathtt{+}} N : \mathrm{Int}}\ {\scriptstyle (\mathtt{+})}
Були
\dfrac{}{\Gamma \vdash \mathtt{true} : \mathrm{Bool}}\ {\scriptstyle (\text{бул})} \qquad \dfrac{}{\Gamma \vdash \mathtt{false} : \mathrm{Bool}}\ {\scriptstyle (\text{бул})} \dfrac{\Gamma \vdash M : \mathrm{Int} \quad \Gamma \vdash N : \mathrm{Int}}{\Gamma \vdash M \mathrel{\mathtt{<}} N : \mathrm{Bool}}\ {\scriptstyle (\mathtt{<})}
\dfrac{\Gamma \vdash C : \mathrm{Bool} \quad \Gamma \vdash M : A \quad \Gamma \vdash N : A}{\Gamma \vdash \mathtt{if}\ C\ M\ N : A}\ {\scriptstyle (\mathtt{if})}
Проверим догадку формально: \ \vdash \lambda f\,x.\,f\ (f\ x) : (\alpha\to\alpha)\to\alpha\to\alpha. Начнём с дерева терма.
\dfrac{x^A \in \Gamma}{\Gamma \vdash x : A}\ {\scriptstyle (\text{акс})} \dfrac{\Gamma \vdash M : A \to B \quad \Gamma \vdash N : A}{\Gamma \vdash M\ N : B}\ {\scriptstyle (\to E)} \dfrac{\Gamma,\ x^A \vdash M : B}{\Gamma \vdash \lambda x.\,M : A \to B}\ {\scriptstyle (\to I)}
Перевернём: корень внизу, листья наверху — так растут деревья вывода.
\dfrac{x^A \in \Gamma}{\Gamma \vdash x : A}\ {\scriptstyle (\text{акс})} \dfrac{\Gamma \vdash M : A \to B \quad \Gamma \vdash N : A}{\Gamma \vdash M\ N : B}\ {\scriptstyle (\to E)} \dfrac{\Gamma,\ x^A \vdash M : B}{\Gamma \vdash \lambda x.\,M : A \to B}\ {\scriptstyle (\to I)}
Подпишем в каждой вершине её подтерм целиком: именно про него будет говорить утверждение типизации в этой вершине.
\dfrac{x^A \in \Gamma}{\Gamma \vdash x : A}\ {\scriptstyle (\text{акс})} \dfrac{\Gamma \vdash M : A \to B \quad \Gamma \vdash N : A}{\Gamma \vdash M\ N : B}\ {\scriptstyle (\to E)} \dfrac{\Gamma,\ x^A \vdash M : B}{\Gamma \vdash \lambda x.\,M : A \to B}\ {\scriptstyle (\to I)}
Применяем правила снизу вверх. Выбора нет: вид подтерма — абстракция, аппликация или переменная — сам называет правило. Здесь \Gamma \equiv f^{\alpha\to\alpha},\ x^\alpha.
\dfrac{x^A \in \Gamma}{\Gamma \vdash x : A}\ {\scriptstyle (\text{акс})} \dfrac{\Gamma \vdash M : A \to B \quad \Gamma \vdash N : A}{\Gamma \vdash M\ N : B}\ {\scriptstyle (\to E)} \dfrac{\Gamma,\ x^A \vdash M : B}{\Gamma \vdash \lambda x.\,M : A \to B}\ {\scriptstyle (\to I)}
\Gamma \vdash f : \alpha\to\alpha (акс)
\Gamma \vdash f : \alpha\to\alpha (акс)
\Gamma \vdash x : \alpha (акс)
\Gamma \vdash f\ x : \alpha (→E)
f^{\alpha\to\alpha},\ x^\alpha \vdash f\ (f\ x) : \alpha (→E)
f^{\alpha\to\alpha} \vdash \lambda x.\,f\ (f\ x) : \alpha\to\alpha (→I)
\vdash \lambda f\,x.\,f\ (f\ x) : (\alpha\to\alpha)\to\alpha\to\alpha (→I)
шаги
1. λf — абстракция: (→I), f^{\alpha\to\alpha} уходит в контекст
2. λx — абстракция: (→I), в контекст уходит x^\alpha
3. f (f x) — аппликация: (→E), две ветки
4. f — переменная: (акс), f^{\alpha\to\alpha} \in \Gamma
5. f x — аппликация: (→E), снова две ветки
6. f — переменная: (акс)
7. x — переменная: (акс), x^\alpha \in \Gamma — все листья закрыты
Утверждение проверено: дерево вывода — это перевёрнутое дерево терма, в котором каждая вершина снабжена контекстом и типом.
Заполните пронумерованные пропуски — типы и названия правил — в дереве вывода для
\ \vdash \lambda x.\,\mathtt{if}\ (x \mathrel{\mathtt{<}} \mathtt{2})\ (x \mathrel{\mathtt{+}} \mathtt{1})\ \mathtt{0} : \mathrm{Int}\to\mathrm{Int}.
\dfrac{ \dfrac{ \dfrac{ \dfrac{}{\Gamma \vdash x : \square_5}\ {\scriptstyle (\text{акс})} \quad \dfrac{}{\Gamma \vdash \mathtt{2} : \mathrm{Int}}\ {\scriptstyle \square_4} }{\Gamma \vdash x \mathrel{\mathtt{<}} \mathtt{2} : \square_3}\ {\scriptstyle (\mathtt{<})} \qquad \dfrac{ \dfrac{}{\Gamma \vdash x : \mathrm{Int}}\ {\scriptstyle \square_7} \quad \dfrac{}{\Gamma \vdash \mathtt{1} : \mathrm{Int}}\ {\scriptstyle (\text{нат})} }{\Gamma \vdash x \mathrel{\mathtt{+}} \mathtt{1} : \mathrm{Int}}\ {\scriptstyle \square_6} \qquad \dfrac{}{\Gamma \vdash \mathtt{0} : \square_8}\ {\scriptstyle (\text{нат})} }{x^{\square_1} \vdash \mathtt{if}\ (x \mathrel{\mathtt{<}} \mathtt{2})\ (x \mathrel{\mathtt{+}} \mathtt{1})\ \mathtt{0} : \mathrm{Int}}\ {\scriptstyle \square_2} }{\vdash \lambda x.\,\mathtt{if}\ (x \mathrel{\mathtt{<}} \mathtt{2})\ (x \mathrel{\mathtt{+}} \mathtt{1})\ \mathtt{0} : \mathrm{Int}\to\mathrm{Int}}\ {\scriptstyle (\to I)}
Здесь \Gamma \equiv x^{\mathrm{Int}}.
\square_1 = \mathrm{Int} (контекст после (\to I)); \ \square_2 = (\mathtt{if}); \ \square_3 = \mathrm{Bool}; \ \square_4 = (\text{нат}); \ \square_5 = \mathrm{Int}; \ \square_6 = (\mathtt{+}); \ \square_7 = (\text{акс}); \ \square_8 = \mathrm{Int} — ветки \mathtt{if} одного типа.
Постройте дерево вывода для \ \vdash \lambda x\,f.\,f\ x : \alpha\to(\alpha\to\beta)\to\beta
Пусть \Gamma \equiv x^\alpha,\ f^{\alpha\to\beta}.
\dfrac{ \dfrac{ \dfrac{ \dfrac{}{\Gamma \vdash f : \alpha\to\beta}\ {\scriptstyle (\text{акс})} \quad \dfrac{}{\Gamma \vdash x : \alpha}\ {\scriptstyle (\text{акс})} }{x^\alpha,\ f^{\alpha\to\beta} \vdash f\ x : \beta}\ {\scriptstyle (\to E)} }{x^\alpha \vdash \lambda f.\,f\ x : (\alpha\to\beta)\to\beta}\ {\scriptstyle (\to I)} }{\vdash \lambda x\,f.\,f\ x : \alpha\to(\alpha\to\beta)\to\beta}\ {\scriptstyle (\to I)}
Поднимите руку, если утверждение выводимо:
(а) \ \vdash \mathbf{K} : \alpha\to\alpha\to\alpha
(б) \ \vdash \mathbf{K} : \alpha\to\alpha\to\beta
(в) \ a^{\alpha\to\alpha} \vdash \mathbf{I}\ a : \alpha\to\alpha
(г) \ a^{\alpha\to\alpha} \vdash a\ b : \alpha
(д) \ \vdash \lambda x.\,x : \mathrm{Int}\to\mathrm{Int}
(е) \ \vdash \lambda x.\,x \mathrel{\mathtt{+}} \mathtt{1} : \alpha\to\alpha
Выводимы (а), (в), (д). В (а) тип не наиболее общий, но дерево строится. В (б) результат — первый аргумент, он типа \alpha. В (г) переменной b нет в контексте. (д) и (е) — снова буквы против констант: вместо буквы \mathrm{Int} подставить можно, а сделать из \mathrm{Int} букву — нет.
Найдите все термы M: \ x^\beta \vdash M : \alpha \to \alpha
Найдите все термы M: \ x^\beta \vdash M : \alpha \to \beta
Найдите все термы M: \ x^\beta \vdash M : \alpha \to \gamma
Сколько замкнутых термов в нормальной форме у каждого типа?
(а) \alpha\to\alpha\to\alpha
(б) (\alpha\to\alpha)\to\alpha\to\alpha
(в) \alpha
(г) \mathrm{Int}
fix факультативноЗадайте \mathtt{fix} полностью: (а) строку в грамматике термов; (б) правило типизации; (в) правило редукции.
(а) \ M ::= \ldots \ \mid\ \mathtt{fix}\ M \qquad (б) \ \dfrac{\Gamma \vdash M : A \to A}{\Gamma \vdash \mathtt{fix}\ M : A}\ {\scriptstyle (\mathtt{fix})}\qquad (в) \ \mathtt{fix}\ M \rightsquigarrow M\ (\mathtt{fix}\ M)
Аргумент \mathtt{fix} — функция от «самой себя»: тип A \to A; результат — неподвижная точка, тип A.
\mathbf{fac} := \mathtt{fix}\ F, \qquad F \equiv \lambda f\,n.\,\mathtt{if}\ (n \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (n \mathrel{\mathtt{*}} f\ (n \mathrel{\mathtt{-}} \mathtt{1}))
Какой тип у F? У \mathbf{fac}?
F : (\mathrm{Int}\to\mathrm{Int})\to\mathrm{Int}\to\mathrm{Int} — принимает «себя» и число; по правилу (\mathtt{fix}) с A := \mathrm{Int}\to\mathrm{Int} получаем \mathbf{fac} : \mathrm{Int}\to\mathrm{Int}.
F \equiv \lambda f\,n.\,\mathtt{if}\ (n \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (n \mathrel{\mathtt{*}} f\ (n \mathrel{\mathtt{-}} \mathtt{1})), \quad \Gamma \equiv f^{\mathrm{Int}\to\mathrm{Int}},\ n^{\mathrm{Int}}
\Gamma \vdash n : \mathrm{Int} (акс)
\Gamma \vdash \mathtt{0} : \mathrm{Int} (нат)
\Gamma \vdash n \mathrel{\mathtt{==}} \mathtt{0} : \mathrm{Bool} (==)
\Gamma \vdash \mathtt{1} : \mathrm{Int} (нат)
\Gamma \vdash n : \mathrm{Int} (акс)
\Gamma \vdash f : \mathrm{Int}\to\mathrm{Int} (акс)
\Gamma \vdash n : \mathrm{Int} (акс)
\Gamma \vdash \mathtt{1} : \mathrm{Int} (нат)
\Gamma \vdash n \mathrel{\mathtt{-}} \mathtt{1} : \mathrm{Int} (−)
\Gamma \vdash f\ (n \mathrel{\mathtt{-}} \mathtt{1}) : \mathrm{Int} (→E)
\Gamma \vdash n \mathrel{\mathtt{*}} f\ (n \mathrel{\mathtt{-}} \mathtt{1}) : \mathrm{Int} (∗)
\Gamma \vdash \mathtt{if}\ (n \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (n \mathrel{\mathtt{*}} f\ (n \mathrel{\mathtt{-}} \mathtt{1})) : \mathrm{Int} (if)
f^{\mathrm{Int}\to\mathrm{Int}} \vdash \lambda n.\,\mathtt{if}\ \ldots : \mathrm{Int}\to\mathrm{Int} (→I)
\vdash F : (\mathrm{Int}\to\mathrm{Int})\to\mathrm{Int}\to\mathrm{Int} (→I)
\vdash \mathtt{fix}\ F : \mathrm{Int}\to\mathrm{Int} (fix)
Раскрыли \mathbf{fac}; дальше единственное правило для \mathtt{fix} — редукция \mathtt{fix}\ M \rightsquigarrow M\ (\mathtt{fix}\ M).
fix F 2
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
Правило (\mathtt{fix}): наружу вышла копия F, внутри остался \mathtt{fix}\ F — запас на следующий виток.
F (fix F) 2
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
\rightsquigarrow_{\mathtt{fix}}\ F\ (\mathtt{fix}\ F)\ \mathtt{2}
Два β-шага: f стало \mathtt{fix}\ F, n стало \mathtt{2}. Перед нами тело F — обычный \mathtt{if} с константами.
if (2 == 0) 1 (2 * fix F (2 − 1))
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
\rightsquigarrow_{\mathtt{fix}}\ F\ (\mathtt{fix}\ F)\ \mathtt{2}
\twoheadrightarrow_\beta\ \mathtt{if}\ (\mathtt{2} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{2} \mathrel{\mathtt{-}} \mathtt{1}))
Константы считаются за шаг: \mathtt{2} \mathrel{\mathtt{==}} \mathtt{0} \rightsquigarrow \mathtt{false}, \mathtt{if} выбрал ветку else, \mathtt{2} \mathrel{\mathtt{-}} \mathtt{1} \rightsquigarrow \mathtt{1}. Снаружи остался \mathtt{2} \mathrel{\mathtt{*}}, внутри — тот же кадр, что в начале.
2 * fix F 1
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
\rightsquigarrow_{\mathtt{fix}}\ F\ (\mathtt{fix}\ F)\ \mathtt{2}
\twoheadrightarrow_\beta\ \mathtt{if}\ (\mathtt{2} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{2} \mathrel{\mathtt{-}} \mathtt{1}))
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{1} — правила (\mathtt{==}), (\mathtt{if}), (\mathtt{-})
Второй виток: снова (\mathtt{fix}), β-шаги и условие; снаружи ещё один множитель.
2 * 1 * fix F 0
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
\rightsquigarrow_{\mathtt{fix}}\ F\ (\mathtt{fix}\ F)\ \mathtt{2}
\twoheadrightarrow_\beta\ \mathtt{if}\ (\mathtt{2} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{2} \mathrel{\mathtt{-}} \mathtt{1}))
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{1} — правила (\mathtt{==}), (\mathtt{if}), (\mathtt{-})
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{1} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{0} — виток 2
Третий виток: копия, β-шаги — и на этот раз \mathtt{0} \mathrel{\mathtt{==}} \mathtt{0} истинно.
2 * 1 * if (0 == 0) 1 (0 * fix F (0 − 1))
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
\rightsquigarrow_{\mathtt{fix}}\ F\ (\mathtt{fix}\ F)\ \mathtt{2}
\twoheadrightarrow_\beta\ \mathtt{if}\ (\mathtt{2} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{2} \mathrel{\mathtt{-}} \mathtt{1}))
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{1} — правила (\mathtt{==}), (\mathtt{if}), (\mathtt{-})
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{1} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{0} — виток 2
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{1} \mathrel{\mathtt{*}} \mathtt{if}\ (\mathtt{0} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{0} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{0} \mathrel{\mathtt{-}} \mathtt{1})) — виток 3
\mathtt{if} вернул \mathtt{1}, ветка с \mathtt{fix}\ F\ (\mathtt{0} \mathrel{\mathtt{-}} \mathtt{1}) выброшена, так и не раскрывшись: \mathtt{fix} разворачивался ровно столько раз, сколько потребовало условие.
2 * 1 * 1 ↠ 2
цепочка
\mathbf{fac}\ \mathtt{2} \rightsquigarrow_{\mathbf{fac}} \mathtt{fix}\ F\ \mathtt{2}
\rightsquigarrow_{\mathtt{fix}}\ F\ (\mathtt{fix}\ F)\ \mathtt{2}
\twoheadrightarrow_\beta\ \mathtt{if}\ (\mathtt{2} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{2} \mathrel{\mathtt{-}} \mathtt{1}))
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{1} — правила (\mathtt{==}), (\mathtt{if}), (\mathtt{-})
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{1} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ \mathtt{0} — виток 2
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{1} \mathrel{\mathtt{*}} \mathtt{if}\ (\mathtt{0} \mathrel{\mathtt{==}} \mathtt{0})\ \mathtt{1}\ (\mathtt{0} \mathrel{\mathtt{*}} \mathtt{fix}\ F\ (\mathtt{0} \mathrel{\mathtt{-}} \mathtt{1})) — виток 3
\twoheadrightarrow\ \mathtt{2} \mathrel{\mathtt{*}} \mathtt{1} \mathrel{\mathtt{*}} \mathtt{1} \twoheadrightarrow \mathtt{2} — правила (\mathtt{==}), (\mathtt{if}), (\mathtt{*})
Дерево вывода типа комбинатора \mathbf{B} для произвольных типов A, B, C — или вывод силлогизма в исчислении высказываний?
\dfrac{ \dfrac{ \dfrac{ \dfrac{ \dfrac{}{\Gamma \vdash {\color{blue}f :}\ B\to C}\ {\scriptstyle (\text{акс})} \qquad \dfrac{ \dfrac{}{\Gamma \vdash {\color{blue}g :}\ A\to B}\ {\scriptstyle (\text{акс})} \quad \dfrac{}{\Gamma \vdash {\color{blue}x :}\ A}\ {\scriptstyle (\text{акс})} }{\Gamma \vdash {\color{blue}g\ x :}\ B}\ {\scriptstyle (\to E)} }{{\color{blue}f}^{B\to C},\ {\color{blue}g}^{A\to B},\ {\color{blue}x}^{A} \vdash {\color{blue}f\ (g\ x) :}\ C}\ {\scriptstyle (\to E)} }{{\color{blue}f}^{B\to C},\ {\color{blue}g}^{A\to B} \vdash {\color{blue}\lambda x.\,f\ (g\ x) :}\ A\to C}\ {\scriptstyle (\to I)} }{{\color{blue}f}^{B\to C} \vdash {\color{blue}\lambda g\,x.\,f\ (g\ x) :}\ (A\to B)\to A\to C}\ {\scriptstyle (\to I)} }{\vdash {\color{blue}\lambda f\,g\,x.\,f\ (g\ x) :}\ (B\to C)\to(A\to B)\to A\to C}\ {\scriptstyle (\to I)}
Дерево вывода типа комбинатора \mathbf{B} для произвольных типов A, B, C — или вывод силлогизма в исчислении высказываний?
\dfrac{ \dfrac{ \dfrac{ \dfrac{ \dfrac{}{\Gamma \vdash \phantom{f :}\ B\to C}\ {\scriptstyle (\text{акс})} \qquad \dfrac{ \dfrac{}{\Gamma \vdash \phantom{g :}\ A\to B}\ {\scriptstyle (\text{акс})} \quad \dfrac{}{\Gamma \vdash \phantom{x :}\ A}\ {\scriptstyle (\text{акс})} }{\Gamma \vdash \phantom{g\ x :}\ B}\ {\scriptstyle (\to E)} }{{\phantom{f}}^{B\to C},\ {\phantom{g}}^{A\to B},\ {\phantom{x}}^{A} \vdash \phantom{f\ (g\ x) :}\ C}\ {\scriptstyle (\to E)} }{{\phantom{f}}^{B\to C},\ {\phantom{g}}^{A\to B} \vdash \phantom{\lambda x.\,f\ (g\ x) :}\ A\to C}\ {\scriptstyle (\to I)} }{{\phantom{f}}^{B\to C} \vdash \phantom{\lambda g\,x.\,f\ (g\ x) :}\ (A\to B)\to A\to C}\ {\scriptstyle (\to I)} }{\vdash \phantom{\lambda f\,g\,x.\,f\ (g\ x) :}\ (B\to C)\to(A\to B)\to A\to C}\ {\scriptstyle (\to I)}
| по Карри | по Чёрчу | |
|---|---|---|
| абстракция | \lambda x.\,M | \lambda x^A.\,M — в домашке \x:a. x |
| количество кода | меньше кода, сложнее задача типовой подсистеме языка | программисту приходится больше писать |
| сколько типов у терма | либо 0, либо \infty | либо 0, либо 1 |
| алгоритм | сложнее: приходится решать систему типовых уравнений (П13) | проще: вся необходимая информация написана в терме |
| в вашем языке | Haskell, OCaml; auto в C++, var в Java и C# |
типы параметров в C, Java, Go |
Позволяют выявлять некоторые классы ошибок:
Механизм абстракции: интерфейс, скрывающий детали реализации
Средство документирования: как использовать сущность
Частичная спецификация поведения
Позволяют генерировать более эффективный низкоуровневый код
В чем подвох с системами типов?
Вспомним: всё, что типизируется, «хорошее», но обратное не всегда верно. Будем «хорошим» считать сильную нормализуемость.
\mathbf{2}\ \mathbf{K} терм сильно нормализуем и редуцируется так:
\mathbf{2}\ \mathbf{K} = \lambda z.\,\mathbf{K}\ (\mathbf{K}\ z) = \lambda z\,a\,b.\,z
Однако протипизировать это не получится.
Противоречие.
\beta-эквивалентность не сохраняет тип
Из лекции известно, что если M редуцируется к N и \Gamma \vdash M : \tau, то \Gamma \vdash N : \tau.
Неправда, что если M редуцируется к N и \Gamma \vdash N : \tau, то \Gamma \vdash M : \tau.
Пример: N = \lambda x.\,x, N : \alpha \to \alpha; M = \lambda x.\,(\lambda y.\,x)\ (x\ \mathbf{I}), и за одно редуцирование M переходит в N, но M : \alpha \to \alpha не выполняется: тогда бы подтерм x\ \mathbf{I} не типизировался, так как \alpha не является стрелочным типом.
\eta-эквивалентность не сохраняет тип
Если \lambda x.\,M\ x : \tau (где x не является свободным в M), то M : \tau.
Если M : \tau, то не обязательно \lambda x.\,M\ x : \tau.
Пример: \mathbf{I} : \alpha \to \alpha, но \lambda x\,y.\,x\ y : (\beta \to \gamma) \to (\beta \to \gamma) нельзя приписать тип \alpha \to \alpha: тогда бы подтерм x\ y не типизировался, так как \alpha не является стрелочным типом.
Практика 3. Типы в λ-исчислении