Основы функционального программирования/Доказательство свойств функций
Материал из Викиучебника
Основы функционального программирования
- Вводная лекция
- Структуры данных и базисные операции:
- Конструирование функций
- Доказательство свойств функций
- Формализация функционального программирования на основе λ-исчисления
- Трансформация программ
Формальная задача: пусть имеется набор функций
, определённых на областях
. Требуется доказать, что для любого набора значений d имеет место некоторое свойство, то есть:
,
где P — рассматриваемое свойство. Например:



Вводится принципиальное ограничение на рассматриваемые свойства — свойства только тотальные, то есть справедливые для всей области D.
Далее рассматриваются некоторые виды областей определения D.
1. D — линейно упорядоченное множество.
Полуформально линейно упорядоченное множество можно определить как такое множество, для каждых элементов которого можно сказать, какой меньше (или больше), либо они равны, то есть:
.
В качестве примера можно привести множество целых чисел. Однако линейно упорядоченные множества встречаются в мире функционального программирования очень редко. Взять хотя бы простейшую структуру, которую очень любят обрабатывать в функциональном программировании — список. Для списков уже довольно сложно определить отношение порядка.
Для доказательства свойств функций на линейно упорядоченных множествах достаточно провести индукцию по данным. То есть достаточно доказать два пункта:
— базис индукции;
— шаг индукции.
В силу того, что структуры данных редко образуют линейно упорядоченные множества, более эффективным способом оказывается применение метода индукции по построению типа D.
2. D — определяется как индуктивный класс
Из прошлой лекции известно, что индуктивный класс определяется через ввод базиса класса (это либо набор каких либо констант
, либо набор первичных типов
. Также индуктивный класс определяется при помощи шага индукции — заданы конструкторы
, определённые над Ai и D, и справедливо, что:
.
В этом случае доказательство свойств функций также резонно проводить в виде индукции по даным. Метод индукции по даным в этом случае также очень прост:
необходимо доказать для базиса класса;- Шаг индукции:
.
Например, для доказательства свойств функций для списков (тип
), достаточно доказать рассматриваемое свойство для двух следующих случаев:
.
.
Доказательство свойств функций над S-выражениями (тип
) можно проводить на основе следующей индукции:
.
.
Пример 23. Доказать, что
.
Для доказательства этого свойства можно использовать только определение типа
и самой функции
(в инфиксной записи используется символ * ).
. Базис индукции доказан.
. Теперь пусть применяется конструктор: a:L. Необходимо доказать, что
. Это делается при помощи применения второго клоза определения функции
:
.
Пример 24. Доказать ассоциативность функции
.
То есть необходимо доказать, что для любых трёх списков L1, L2 и L3 имеет место равенство (L1 * L2) * L3 = L1 * (L2 * L3). При доказательстве индукция будет проводиться по первому операнду, то есть списку L1:
:
.
.
- Пусть для списков L1, L2 и L3 ассоциативность функции
доказана. Необходимо доказать для (a:L1), L2 и L3:
.
.
Как видно, последние два выведенных выражения равны, так как для списков L1, L2 и L3 ассоциативность полагается доказанной.
Пример 25. Доказательство тождества двух определений функции
.
Определение 1:
![\operatorname{reverse}\ [\,] = [\,]](http://upload.wikimedia.org/math/0/2/d/02dfe1d95793086a8cc4c55208f216a0.png)
![\operatorname{reverse}\ (H : T) = (\operatorname{reverse}\ T) * [H]](http://upload.wikimedia.org/math/2/4/2/24236d455f3859788354610dd3be8ffa.png)
Определение 2:
![\operatorname{reverse}'\; L = \operatorname{rev}\ L [\,]](http://upload.wikimedia.org/math/5/0/f/50fe801de39ef461715d0e7728cc478a.png)
![\operatorname{rev}\ [\,]\ L = L](http://upload.wikimedia.org/math/a/9/6/a9692716a1bda52deb54ab7f710af429.png)

Видно, что первое определение функции обращения списков — это обычное рекурсивное определение. Второе же определение использует аккумулятор. Требуется доказать, что:
.
1. Базис —
:
.
.
2. Шаг — пусть для списка L тождество функций
и
доказано. Необходимо доказать его для списка (H:L).
.
.
Теперь необходимо доказать равенство двух последних выведенных выражений для любых списков над типом A. Это также делается по индукции:
2.1. Базис —
:
.
.
2.2. Шаг — L = (A:T):
.
.
Здесь произошло выпадение в дурную бесконечность. Если дальше пытаться проводить доказательство по индукции для новых выведенных выражений, то эти самые выражения будут всё усложняться и усложняться. Но это не причина для того, чтобы отчаиваться, ибо доказательство всё равно можно провести. Надо просто придумать некую «индукционную гипотезу», как это было сделано в предыдущем примере.
Индукционная гипотеза:
. Эта индукционная гипотеза является обобщением выражения
.
Базис индукции для этой гипотезы очевиден. Шаг индукции в применении к выражению в пункте 2.2 выглядит следующим образом:
![\Big(\operatorname{reverse}'\; (A : T)\Big) * L_2 = (\operatorname{rev}\ (A : T)\ [\,]) * L_2 = (\operatorname{rev}\ T\ [A]) * L_2 =](http://upload.wikimedia.org/math/1/f/7/1f76d1d617c6b6b95d99e107c2e74ed6.png)
.
.
Что и требовалось доказать.
Общий вывод: в общем случае для доказательства свойств функций методом индукции может потребоваться применение некоторых эвристических шагов, а именно введение индукционных гипотез. Эвристический шаг — это формулирование утверждения, которое ниоткуда не следует. Таким образом, доказательство свойств функций есть своего рода творчество.