66
первой главы). В функциональном программировании, однако, функции
являются значениями «первого класса», так что подобные описания не
только возможны, но и достаточно часто встречаются. В частности,
функция, определяющая суперпозицию двух других функций, не только
может быть легко описана средствами языка, но и является одним из
самым важных инструментов построения программ, и
поэтому содержится
в языке в виде стандартной операции.
Мы, однако, начнем не с описания функции суперпозиции, а с
других примеров, в которых функции используются в качестве аргументов
других функций. В качестве первого примера рассмотрим стандартную
функцию обработки списков map, которая, получив в качестве аргументов
список и функцию преобразования элементов этого списка
, выдает в
качестве результата список из преобразованных элементов, полученных
применением функционального параметра последовательно к каждому
элементу списка. Если, например, функция sqr возводит в квадрат целое
число, то с помощью функции map можно, имея список целых чисел,
получить список их квадратов:
map sqr [1, 2, 5, -2] ⇒ [1, 4, 25, 4]
Функция map – это стандартная функция, определенная в ядре
языка. Однако, по уже сложившейся традиции приведем ее описание
заново. Прежде всего, давайте определим ее тип. Первым аргументом
нашей функции является функция, которая в нашем случае имеет один
целый аргумент и возвращает целый результат. Тип этого первого
аргумента будет Integer->Integer. Второй аргумент и
результат
функции – это списки целых типа [Integer]. Таким образом тип
функции map будет выглядеть так:
map :: (Integer -> Integer) -> [Integer] -> [Integer]
На самом деле не столь важно, что исходный и результирующий
списки содержат именно элементы типа Integer. Фактически исходные
элементы могут иметь произвольный тип a. Тогда, если функция,
являющаяся первым аргументом функции map, имеет тип (a -> b), то
результирующий список будет содержать элементы типа b. Теперь мы
готовы описать полностью функцию map, включая
и ее тип (листинг 2.6).
Листинг 2.6. Определение функции отображения списков – map
map :: (a -> b) -> [a] -> [b]
-- результат применения map к пустому списку - пустой список
map _ [] = []
map func (x:s) = (func x):(map func s)
Первое уравнение определяет результат работы отображения в
случае пустого списка. Понятно, что в этом случае первый аргумент
функции не используется вовсе, так как результатом будет пустой список