11.9. Типы-суммы 107
рая, принимая образец p и значение v, либо терпит неудачу (что означает, что значение v пе со-
ответствует образцу), либо выдает в качестве результата подстановку, переводящую переменные,
содержащиеся в p, в соответствующие части v. Например, match {x, y}, {5, true} порождает
подстановку x 5, y true , сопоставление match x, {5, true} порождает x {5, true} , а
match {x}, {5, true} терпит неудачу. Правило E-LetV с помощью match вычисляет подстановку
для переменных в p.
Сама функция match определяется отдельным набором правил вывода. Правило M-Var утвержда-
ет, что сопоставление с переменной всегда завершается успешно, и возвращает подстановку, пере-
водящую переменную в значение, с которым производится сопоставление. Правило M-Rcd говорит,
что, для того, чтобы сопоставить образец-запись {l
i
=p
i
i 1..n
} со значением-записью {l
i
=v
i
i 1..n
}
(при этом у них должна быть одинаковая длина и одинаковые метки полей), нам нужно по отдель-
ности сопоставить каждый подобразец p
i
с соответствующим подзначением v
i
, получая при этом
подстановку σ
i
, и построить окончательный результат в виде композиции всех таких подстано-
вок. (Мы требуем, чтобы ни одна переменная не встречалась в образце более одного раза, так что
композиция подстановок будет просто их объединением.)
Покажите, как к этой системе добавить типы.
1. Введите правила типизации для новых конструкций (при этом Вы можете делать любые нуж-
ные Вам изменения в синтаксисе).
2. Постройте план доказательства теорем о сохранении и продвижении для всего полученного ис-
числения. (Строить полные доказательства необязательно; достаточно сформулировать тре-
буемые леммы и расположить их в правильном порядке.)
11.9. Типы-суммы
Во многих программах требуется работать с гетерогенными наборами данных. К примеру, вершина
в бинарном дереве может быть либо концевой, либо внутренней вершиной с двумя дочерними; подобным
образом, список может быть либо пустым (nil), либо cons-ячейкой, состоящей из головы и хвоста,
5
вершина абстрактного синтаксического дерева внутри компилятора может представлять переменную,
абстракцию, применение функции и т. д. Механизм теории типов, поддерживающий программирование
такого рода, называется вариантные типы.
Прежде чем ввести варианты в общем случае (§11.10), рассмотрим сначала более простой случай
бинарных типов-сумм. Тип-сумма описывает множество значений, выбираемых ровно из двух данных
типов. Допустим, например, что у нас есть типы
ФизАдрес
= фио{: String , адрес: String };ВиртАдрес
= имя{: String , email : String };
представляющие различные виды записей в адресной книге. Если мы хотим обрабатывать оба вида за-
писей единообразно (например, если нам требуется построить список, содержащий записи обоих видов),
можно ввести тип-сумму
6
Адрес
= ФизАдрес + ВиртАдрес;
каждый из элементов которого представляет собой либо ФизАдрес, либо ВиртАдрес.
Элементы этого типа создаются путем постановки тегов на элементы типов-компонент ФизАдрес
и ВиртАдрес. Например, если pa имеет тип ФизАдрес, то inl pa будет иметь тип Адрес. (Имена тегов
inl и inr помогают представить их как функции
inl : ФизАдрес -> ФизАдресВиртАдрес+;
inr : ВиртАдрес -> ФизАдресВиртАдрес+;
5
Эти примеры, подобно большинству случаев реального использования вариантных типов, используют также рекур-
сивные типы — хвост списка сам является списком, и т. д. К рекурсивным типам мы вернемся в Главе 20.
6
Интерпретатор fullsimple на самом деле не поддерживает описанные здесь конструкции с бинарными суммами —
вместо этого есть более общая конструкция с вариантами, описанная ниже.
rev. 104