учебники, программирование, основы, введение в,
создание сайтов одесса- YouTube

 

Ламбда-исчисление как формализация языка функционального программирования

Пожалуй, наиболее продуктивной формализацией понятия «функция» стала математическая теория, известная сегодня под названием ламбда-исчисления. Более точно это исчисление следует называть исчислением ламбда-конверсий.
Под конверсией понимается преобразование объектов исчисления (а в программировании – функций и данных) из одной формы в другую. Исходной задачей в математике было стремление к упрощению формы выражений. В программировании именно эта задача не является столь существенной, хотя, как мы увидим в дальнейшем, использование ламбда-исчисления как исходной формализации может способствовать упрощению вида программы, т.е. вести к оптимизации программного кода.
Кроме того, конверсии обеспечивают переход к вновь введенным обозначениям и, таким образом, позволяют представлять предметную область в более компактном или более детальном виде, или, говоря математическим языком, изменять уровень абстракции по отношению к предметной области. Эту возможность широко используют также языки объектно-ориентированного и структурно-модульного программирования в иерархии объектов, фрагментов программ и структур данных. На этом же принципе основано взаимодействие компонентов приложения в .NET. Именно в этом смысле переход к новым обозначениям является одним из важнейших элементов программирования в целом, и именно ламбда-исчисление (в отличие от многих других разделов математики) представляет собой адекватный способ формализации переобозначений.
Поскольку основным объектом ламбда-исчисления является функция, этот подход весьма продуктивен при моделировании языков функционального программирования.
Заметим, однако, что под словом «функция» в математической формализации и программной реализации имеются ввиду различные понятия.
Напомним, что определение функции в математике было сформулировано в лекции 3.
В свою очередь, функцией в языке программирования называется конструкция этого языка, описывающая правила преобразования аргумента (так называемого фактического параметра) в результат.
Напомним ход эволюции теорий, лежащих в основе современного подхода к ламбда-исчислению.
Как видно из вступительной лекции, практически все ранее созданные формализации языков функционального программирования (включая абстрактные машины и средства оптимизации вычислений) базируются на фундаменте ламбда-исчисления в той или иной его форме.

Перейдем к описанию ламбда-исчисления как формальной системы. Согласно математической практике, необходимо определить следующие элементы теории:

  • алфавит;
  • утверждения;
  • аксиомы;
  • правила вывода.

При этом под алфавитом понимается множество символов, допустимых в нотации той или иной формализации.
Утверждения устанавливают правила образования терминальных символов математической теории.
Под аксиомами понимаются элементарные утверждения, которые считаются истинными без необходимости доказательства истинности.
Правила вывода определяют законы преобразования одних символов (объектов), исследуемых в теории, в другие объекты.
Рассмотрим алфавит ламбда-исчисления.
Допускаются элементы четырех видов:

  1. константы;
  2. переменные;
  3. выражения (или термы);
  4. специальные символы.

При этом принимаются следующие обозначения.
Константы c1 , c2 , ... обозначаются малыми буквами латинского алфавита, возможно, с индексами.
Переменные x, y, ... обозначаются малыми буквами латинского алфавита, возможно, с индексами.
Выражения (или, иначе, термы) M, N, ... обозначаются заглавными буквами латинского алфавита, возможно, с индексами.
Допускается использование следующих специальных символов (взяты в кавычки и разделены запятыми): «(», «)», «.»
Рассмотрим далее порядок конструирования допустимых для заданного алфавита ламбда-выражений, или, иначе, термов.
Ламбда-термы строятся по индукции (порядок построения можно считать определением) следующим образом.
Базис индукции: любая переменная или константа является ламбда-термом по определению.
Шаг индукции: если M, N – произвольные ламбда-термы и x – произвольная переменная, то справедливо, что:

  • во-первых, выражение (λx.M) является допустимым ламбда-термом;
  • во-вторых, выражение (MN) является допустимым ламбда-термом.

Заметим, что при этом ламбда-выражение (MN) обозначает операцию аппликации (или применения функции к аргументу), а ламбда-выражение (λx.M) – операцию абстракции.
Кроме того, примем, что никакой другой набор символов не является допустимым ламбда-термом.
После определения алфавита и порядка построения допустимых ламбда-выражений посредством операций аппликации и абстракции перечислим аксиомы ламбда-исчисления.
Отметим, что употребляемый ниже символ «=» понимается в ламбда-исчислении как обозначение отношения конвертируемости, которым связываются соединенные этим значком ламбда-выражения. Конвертируемость двух ламбда-выражений означает, что одно ламбда-выражение может быть преобразовано в другое. Отношение конвертируемости моделирует переобозначения и во многих отношениях, напоминает процесс программирования.
Следующие аксиомы задают свойства отношения конвертируемости:
()     λx.a = λz.[z/x]a;
(β)     (λx.a)b = [b/x]a.
Аксиома () означает возможность подстановки терма z вместо всех вхождений переменной x в ламбда-выражение а .
Аксиома (β) означает возможность редукции (то есть упрощения вида) ламбда-выражения в левой части путем подстановки b вместо всех вхождений переменной x в ламбда-выражение а. Фактически редукция означает возможность создания (в ламбда-исчислении или на языке программирования) одной функции (ламбда-выражения) как сокращенной записи другой функции (ламбда-выражения).
Перечислим правила вывода термов, которые задают характеристики отношения конвертируемости:
(μ)     если a=b, то ca=cb;
(ν)     если a=b, то ac=bc;
(ξ)      если a=b, то lx.a=lx.b;
(ρ)     a=a (рефлексивность);
(σ)     если a=b, то b=a (симметричность);
(τ)      если a=b и b=c, то a=c (транзитивность).
Как видно из перечисленных выше свойств, отношение конвертируемости обладает, в частности, свойствами рефлексивности, симметричности и транзитивности. Первое из только что перечисленных свойств означает конвертируемость произвольного ламбда-выражения к самому себе, второе – двунаправленность вывода ламбда-выражений посредством конверсии, а третье – возможность опускать промежуточные этапы конверсии для цепочек вывода.
Именно в силу фундаментальности отношения конвертируемости для ламбда-исчисления эта теория известна также под другим, более точно характеризующим ее суть названием, а именно, как исчисление ламбда-конверсий.
К сожалению, относительная простота описания предыдущих этапов формальной теории ламбда-конверсий (алфавита, аксиом и правил вывода) порождает довольно громоздкие выкладки при моделировании вычислений.
В этой связи из соображения экономии пространства для вывода соотношений принимаются следующие соглашения, позволяющие значительно сократить запись и увеличить удобство прочтения и обработки ламбда-выражений.
Во-первых, скобки для операции аппликации восстанавливаются по ассоциации влево, например:
xy = (xy), xyz = ((xy)z), ...
Во-вторых, избыточные скобки могут опускаться, например:
(xy) = xy, ((xy)z) = xyz, ...
В-третьих, скобки для операции абстракции восстанавливаются по ассоциации вправо, например:
λxy.M = (λx.(λy.M)), λxyz.M = (λx.( λy.(λz.M))), ...
Проиллюстрируем формальное описание исчисления ламбда-конверсий необходимыми содержательными примерами. Рассмотрим следующие шесть ламбда-термов, возможно, с цепочками вывода:

  1. x;
  2. 1;
  3. lx.x;
  4. lx.x + 1;
  5. (lx.x + 1)2 = [2/x](x + 1) = 2+1 = 3;
  6. a $ b.

Согласно правилам построения алфавита, первый из ламбда-термов является переменной, а второй – константой.
Третий ламбда-терм, согласно правилам построения выражений, представляет собой ламбда-абстракцию переменного терма x к самому себе, т.е. определяет функцию тождества.
Четвертый ламбда-терм отличается от третьего тем, что добавляет к аргументу x константу 1, т.е. определяет функцию инкремента (или прибавления единицы). Заметим, что в алфавите ламбда-исчисления отсутствует функция сложения как таковая, так что возможны различные интрепретации символа «+» (будем считать его далее «встроенной» функцией сложения).
Пятый ламбда-терм обозначает подстановку согласно аксиоме () константы 2 вместо всех вхождений x в выражение x+1 (вычисление значения функции в число 3 возможно при корректной интерпретации символа «+»).
Шестой ламбда-терм недопустим из-за вхождения неопределенного символа «$».
Проиллюстрируем соответствие между математической моделью языка функционального программирования – ламбда-исчислением и языком функционального программирования SML.
Несмотря на то, что мы еще не изучали синтаксис языка, соответствие между ламбда-исчислением и функциональным языком настолько естественно, что сопоставление ламбда-термов SML-выражениям происходит практически интуитивно и в дальнейших комментариях не нуждается.
Приведем фрагменты SML-программ, соответствующих допустимым ламбда-термам из предыдущего списка:

  1. x (переменная, тип которой определяется в процессе трансляции на этапе контроля типизации в соответствии с выводом типов);
  2. 1 (константа);
  3. fn x => x (функция тождества);
  4. fn x => x+1 (функция инкремента);
  5. (fn x => x+1) 2 (вычисление значения функции, в результате выполнения получается целое число 3).

Продолжим иллюстрацию соответствия между программами на языке SML и ламбда-выражениями, исследовав операцию аппликации функции к аргументу.
Рассмотрим описание функции инкремента:
fun f x = 1+x;
Здесь нужно учитывать, что в общем случае функция f языка программирования SML, имеющая формальный параметр x и тело b, задается следующим описанием:
fun f x = b;
Для вычисления значения выражения необходимо произвести аппликацию функции к данному выражению; для аппликации функции f к целому числу 4 нужно записать:
f 4;
При вычислении значения функции аппликация производится к ближайшему аргументу. Так, запись
f 2 + 3;
означает порядок аппликации (f2)+3, а не f(2+3), т.е. находится в полном соответствии с соглашениями о скобках, принятыми в ламбда-исчислении.
Рассмотрев формальное построение исчисления ламбда-конверсий (алфавит, аксиомы и правила вывода выражений) и сопоставив основные элементы (переменная, константа) и операции (аппликация, подстановка) этой теории с базовыми элементами (переменная, константа) и элементарными программами (объявление и аппликация функции) языка SML, можно сделать вывод о следующих несомненных преимуществах ламбда-исчисления как математической модели языка функционального программирования:

  1. лаконичность (ограниченный необходимыми элементами алфавит, два способа построения выражений – аппликация и абстракция, небольшое количество аксиом и правил вывода);
  2. интуитивная ясность (обозначения являются краткими и понятными);
  3. иллюстративность (ламбда-термы легко интерпретируются не только с помощью алгебраической записи, но и посредством визуальной интерпретации в виде графов, причем редукция, т.е. упрощение вида графов, соответствует бета-редукции ламбда-термов);
  4. полнота (в ламбда-исчислении можно представить произвольную, в частности, сколь угодно сложную, функцию);
  5. естественная близость к языкам функционального программирования (SML, Scheme, Haskell, Miranda, Hope, Clean) была проиллюстрирована на примерах программ на языке SML.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика