До сих пор рассматриваемые нами парадигмы программирования 
воспринимались нами как некоторые "полезные надстройки над императивным 
программированием". Уже отмечалось, например, что параллельное 
программирование - это программирование в терминах взаимодействия 
некоторых одновременно работающих абстрактных вычислителей, и почти 
ничего не говорили о вычислительной модели, на которой основаны 
отдельные элементы этой системы. Мы ничего не сказали о том, на каком 
языке описаны обработчики сообщений у объектов (кроме того, что в этих 
языках основной операцией является посылка сообщения). Функциональное 
программирование представляет из себя одну из альтернатив императивному 
подходу.
В императивном программировании алгоритмы - это описания
 последовательно исполняемых   операций. Здесь существует понятие 
"текущего шага исполнения" (то есть, времени), и "текущего состояния", 
которое меняется с течением этого времени. 
В функциональном 
программировании понятие времени отсутствует. Программы являются 
выражениями, исполнение программ заключается в вычислении этих 
выражений. Практически все математики, сами того не замечая, занимаются 
функциональным программированием, описывая, например, чему равно 
абсолютное значение произвольного вещественного числа.
Императивное
 программирование основано на машине Тьюринга-Поста - абстрактном 
вычислительном устройстве, предложенном на заре алгоритмической эры для 
описания алгоритмов. Функциональное программирование основано на более 
естественном с математической точки зрения формализме - 
лямбда-исчислении Черча.
Как правило, рассматривают так 
называемое "расширенное лямбда-исчисление". Его грамматику можно описать
 следующим образом (жаль, что не в любой локализации есть символ 
"лямбда"):
Выражение ::= Простое выражение | Составное выражение
Простое выражение ::= Константа | Имя
Составное выражение ::= Лямбда-абстракция | Применение | Квалифицирванное выражение | Ветвление
Лямбда-абстракция ::=  lambda Имя  -> Выражение end
Применение ::= ( Выражение Выражение )
Квалифицированное выражение ::= let ( Имя = Выражение ; )* in Выражение end
Ветвление ::= if Выражение then Выражение (elseif Выражение then Выражение)* else Выражение end
Константами в расширенном лямбда-исчислении могут быть числа, кортежи, списки, имена предопределенных функций, и так далее. 
Результатом
 вычисление применения предопределенной функции к аргументам будет 
значение предопределенной функции в этой "точке". Результатом применения
 лямбда-абстракции к аргументу будет подстановка аргумента в выражение -
 "тело" лямбда-абстракции. Сами лямбда-абстракции так же являются 
выражениями, и, следовательно, могут быть аргументами.
Вы уже 
заметили, что лямбда-абстракции имеют всего один аргумент. В то же 
время, функции в традиционном понимании не обязаны быть одноместными. 
Представления функций от нескольких аргументов можно достичь двумя 
способами:
1.) Считать, что аргумент является кортежем. Например, 
apply = lambda (f, x) -> ( f x ) end можно понимать как apply = 
lambda y -> ( ( first y ) ( second y ) ) end.
2.) Понять, что 
множество вычислимых функций X * Y -> Z очевидным образом 
взаимнооднозначно отображается в множество вычислимых функций X -> (Y
 -> Z). Так, apply = lambda f -> lambda x -> (f x) end end.
Когда
 нам надоест ставить скобки вокруг применения функций к аргументам, мы 
можем объявить операцию применения функции (которую мы при записи 
опускаем, так же, как в математике принято не писать явно символ 
умножения) левоассоциативной, то есть, понимать запись вида f x y как 
((f x) y). Это - традиционное соглашение, поэтому никаких "стандартов" 
мы при этом не нарушаем.
Чистое лямбда-исчисление Черча позволяет
 обходится исключительно именами, лямбда-абстракциями от одного 
аргумента и применениями выражений к выражениям. Оказывается, в этих 
терминах можно описать и "предопределенные" константы (числа и т.п.), 
структуры данных (списки, кортежи...), логические значения и ветвление. 
Более того, в чистом лямбда-исчислении можно обойтись без 
квалифицированных выражений, и, следовательно, выразить рекурсию, не 
используя для этого употребления имени функции в теле функции. Некоторые
 экспериментальные модели функционального программирования позволяют 
обходится без каких-либо имен вообще. Подробнее об этом можно почитать в
 специальной литературе, например, в книге Филда и Харрисона 
"Функциональное программирование".
Функциональное программирование обладает следующими двумя примечательными свойствами:
1.) Аппликативность: программа есть выражение, составленное из применения функций к аргументам.
2.)
 Настраиваемость: так как не только программа, но и любой программный 
объект (в идеале) является выражением, можно легко порождать новые 
программные объекты по образцу, как значения соответствующих выражений 
(применение порождающей функции к параметрам образца).
Настраиваемость
 активно используется в таком направлении программирования, как generic 
programming. Основная задача, решаемая в рамках это направления - 
создание максимально универсальных библиотек, ориентированных на решение
 часто встречающихся подзадач (обработка агрегатных данных; потоковый 
ввод-вывод; взаимодействие между программами, написанными на разных 
языках и различающихся в деталях семантики; универсальные оконные 
библиотеки). Эти направления наиболее ярко представлены в STL - 
стандартной библиотеке шаблонов (контейнеров) языка Си++, а так же - в 
реализации платформы .NET фирмы MicroSoft. Нередко в разговорах о пользе
 функционального программирования можно услышать следующее утверждение: 
"самые крупные специалисты по функциональному языку Haskell в настоящее 
время находятся в MicroSoft Research".
Для обеспечения видовой 
корректности программ в функциональные языки вводят специальные системы 
типов, ориентированные на поддержку настраиваемости. Как правило, 
трансляторы функциональных языков могут самостоятельно определять типы 
выражений, без каких-либо описаний типов вообще. Так, функция add = 
lambda x -> lambda y -> x+y end end будет иметь тип number -> 
number -> number, а уже рассматриваемая нами функция apply - тип 
any(X).any(Y).(X->Y)->X->Y, где any обозначает "квантор 
всеобщности" для типов, а X и Y являются переменными.
Можно 
заметить, что так как порядок вычисления подвыражений не имеет значения 
(благо "состояния" у функциональной программы нет), функциональное 
программирвание может быть естественным образом реализовано на 
платформах, поддерживающих параллелизм. "Потоковая модель" 
функционального программирования, о которой так же можно почитать у 
Филда и Харрисона, является естественным представлением функиональных 
программ в терминах систем взаимодействующих процессов. 
Функциональное
 программирование, как и другие модели "неимперативного" 
программирования, обычно применяется для решения задач, которые трудно 
сформулировать в терминах последовательных операций. Практически все 
задачи, связанные с искусственным интеллектом, попадают в эту категорию.
 Среди них следует отметить задачи распознавания образов, общение с 
пользователем на естественном языке, реализацию экспертных систем, 
автоматизированное доказательство теорем, символьные вычисления. Эти 
задачи далеки от традиционного прикладного программирования, поэтому им 
 уделяется не так много внимания в учебных программах по информатике.
		
	 

