Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Funktsionalnoe_i_logicheskoe_programmirovanie.doc
Скачиваний:
17
Добавлен:
19.01.2023
Размер:
1.75 Mб
Скачать

Лабораторная работа 3. Функции высших порядков.

Функции высших порядков являются отличительной особенностью функционального программирования. Кратко дать определение функции высшего порядка можно так – это функция, имеющая аргументами другие функции или возвращающая в качестве результата другую функцию.

Рассмотрим сначала две функции, являющиеся предикатами, то есть возвращающими логические значения. Функция any имеет два аргумента и проверяет, содержит ли второй аргумент – список хотя бы один элемент, удовлетворяющий первому аргументу. Первый аргумент этой функции сам является функцией, возвращающей логическое значение.

Функция all проверяет выполнение первого аргумента для всех элементов своего второго аргумента:

Первый аргумент может быть некоторой встроенной функций, функцией, определенной пользователем, лямбда-функцией или локальной функцией, вводимой с помощью where. Далее при разборе заданий лабораторной работы продемонстрированы все эти возможности.

Одной из важнейших функций высшего порядка является функция map, встречающаяся во всех функциональных языках и даже в декларативных, таких как C++, Ruby, Python и других. Эта функция применяет свой первый аргумент – функцию последовательно к каждому элементу второго аргумента – списка. Вот примеры её вызова:

Функция filter оставляет во втором аргументе списке только элементы, удовлетворяющие первому аргументу – предикату:

Функция zip, вообще говоря, не являющаяся функцией высшего порядка, позволяет из двух списков создать список кортежей, объединяющих попарно элементы списков:

Заметьте, что длина результирующего списка будет равна длине кратчайшего из списков аргументов. Если же списки у нас одного типа, то к ним можно применить функцию высшего порядка zipWith, которая применяет свой первый аргумент-функцию к каждой паре элементов второго и третьего аргументов – списков:

Функцией, производящей обратное к zip преобразование, является функция unzip:

Комбинируя эти функции, можно решать задачи, связанные с обработкой индексов элементов списка. Например, получение списка индексов четных элементов числового списка:

Функция $ понижает приоритет функции, в данном примере использована как замена вложенных скобок. Функция (.) означает композицию функций в математическом смысле, её определение в Haskell:

В модуле List, впрочем, определены функции, упрощающие решение упомянутых задач. Приведем несколько примеров без подробного описания функций, в большинстве случаев из примера ясно, как работает функция.

Также в модуле List определена функция sort, сортирующая числовой список в порядке неубывания. Но во многих случаях требуется сортировать более сложные структуры данных, чем простой список. В этом случае надо воспользоваться функцией высшего порядка sortBy, первым аргументом которой будет функция сравнения. Например, для сортировки списка строк по длине можно написать так:

Здесь в качестве первого аргумента написана лямбда-функция, указывающая, как именно надо сравнивать два аргумента. Данную функцию следует использовать при выполнении задания 6 лабораторной работы.

Аналогично, существуют функции высшего порядка nubBy, deleteBy, deleteFirstsBy (By-вариант \\), unionBy, intersectBy, groupBy, sortBy, insertBy, maximumBy, minimumBy. Например, для удаления из списка кортежей элементов с повторяющейся суммой можно использовать:

При выполнении третьего задания данной лабораторной работы будут полезны функции высшего порядка из модуля Prelude, позволяющие разбивать или делить список на части по какому-либо условию, приведенные в таблице 3.1.

Таблица 3.1. Функции высшего порядка разделения списка.

Описание

Имя функции

Пример

Получает список первых элементов, удовлетворяющих условию

takeWhile

Отбрасывает первые элементы, удовлетворяющие условию

dropWhile

Разбивает список на кортеж двух списков – первый содержит первые элементы, удовлетворяющие условию, второй – все остальные элементы

span

Разбивает список на кортеж двух списков – в первом первые элементы, не удовлетворяющие условию, во втором – все остальные элементы

break

Разбивает список на кортеж двух списков – в первом первые n элементов, во втором – все остальные элементы

splitAt

Среди функций высшего порядка модуля Prelude есть несколько функций, называемых свертками. Они позволяют применять функцию-параметр последовательно к элементам списка. В зависимости от порядка применения функции к аргументу-списку есть левая и правая свертки. Многие стандартные функции, например, sum, product, maximum, minimum, reverse определены с помощью функций-сверток. Ознакомьтесь с ними в таблице 3.2.

Таблица 3.2. Функции-свертки.

Описание

Имя функции

Пример

Примечание

Правая свертка с аккумулятором

foldr

foldr f a [x1,x2,..,xn] =

=f x1 (f x2 (..(f xn a))..)

foldr (-) 20 [2,5,3] =

2-(5-(3-20))

Левая свертка с аккумулятором

foldl

foldl f a [x1,x2,..,xn] =

=f (f (f a x1) x2)..) xn)

foldl (-) 20 [2,5,3] =

((20-3)-5)-2

Правая свертка

foldr1

foldr f a [x1,x2,..,xn] =

=f x1 (f x2 (..(f xn-1 xn ))..)

foldr1 (-) [20,5,3] =

(20-(5-3))

Левая свертка

foldl1

foldl f a [x1,x2,..,xn] =

=f (f (f x1 x2) x3)..) xn)

foldl1 (-) [20,5,3] =

((20-5)-3)

При выполнении заданий 5 и 7 следует помнить, что в Haskell можно работать с функциями, как с данными. Функции могут быть элементами списков или кортежей и подвергаться применению списочных или кортежных функций. При вызове функций с аргументами–функциями последние могут заключаться в круглые скобки. Например, применение каждой из списка функций к аргументу 5:

.