Учебник по Haskell - [34]

Шрифт
Интервал

. Далее идёт

выражение, которое содержит определение функции.

Отметим, что лямбда функции могут принимать несколько аргументов, в предыдущем определении мы

могли бы написать:

filter :: (a -> Bool) -> ([a] -> [a])

filter = \p xs -> case xs of

...

но это лишь синтаксический сахар, который разворачивается в предыдущую запись.

Для тренировки определим несколько стандартных функций для работы с кортежами с помощью лямбда-

функций (все они определены в Prelude):

fst :: (a, b) -> a

fst = \(a, _) -> a

snd :: (a, b) -> b

snd = \(_, b) -> b

swap :: (a, b) -> (b, a)

swap = \(a, b) -> (b, a)

Обратите внимание на то, что все функции словно являются константами. Они не содержат аргументов.

Аргументы мы “пристраиваем” с помощью безымянных функций.

Определим функции преобразования первого и второго элемента кортежа (эти функции определены в

модуле Control.Arrow)

first :: (a -> a’) -> (a, b) -> (a’, b)

first = \f (a, b) -> (f a, b)

second :: (b -> b’) -> (a, b) -> (a, b’)

second = \f (a, b) -> (a, f b)

Также в Prelude есть полезные функции, которые превращают функции с частичным применением в

обычны функции и наоборот:

curry :: ((a, b) -> c) -> a -> b -> c

curry = \f -> \a -> \b -> f (a, b)

uncurry :: (a -> b -> c) -> ((a, b) -> c)

uncurry = \f -> \(a, b) -> f a b

66 | Глава 4: Декларативный и композиционный стиль

Функция curry принимает функцию двух аргументов для которой частичное применение невозможно.

Это имитируется с помощью кортежей. Функция принимает кортеж из двух элементов. Функция curry (от

слова каррирование, частичное применение) превращает такую функцию в обычную функцию Haskell. А

функция uncurry выполняет обратное преобразование.

С помощью лямбда-функций можно имитировать локальные переменные. Так например можно перепи-

сать формулу для вычисления площади треугольника:

square a b c =

(\p -> sqrt (p * (p - a) * (p - b) * (p - c)))

((a + b + c) / 2)

Смотрите мы определили функцию, которая принимает параметром полупериметр p и передали в неё

значение ((a + b + c) / 2). Если в нашей функции несколько локальных переменных, то мы можем

составить лямбда-функцию от нескольких переменных и подставить в неё нужные значения.

4.5 Какой стиль лучше?

Основной критерий выбора заключается в том, сделает ли этот элемент код более ясным. Наглядность

кода станет залогом успешной поддержки. Его будет легче понять и улучшить при необходимости.

Далее мы рассмотрим несколько примеров определений из Prelude и подумаем, почему был выбран тот

или иной стиль. Начнём с класса Ord и посмотрим на определения по умолчанию:

-- Тип упорядочивания

data

Ordering

=

LT | EQ | GT

deriving (Eq, Ord, Enum, Read, Show, Bounded)

class

(Eq a) => Ord a

where

compare

:: a -> a -> Ordering

(< ), (<=), (>=), (> ) :: a -> a -> Bool

max, min

:: a -> a -> a

-- Минимальное полное определение:

--

(<=) или compare

-- Использование compare может оказаться более

-- эффективным для сложных типов.

compare x y

| x == y

=

EQ

| x <= y

=

LT

| otherwise =

GT

x <= y

=

compare x y /= GT

x <

y

=

compare x y == LT

x >= y

=

compare x y /= LT

x >

y

=

compare x y == GT

max x y

| x <= y

=

y

| otherwise =

x

min x y

| x <= y

=

x

| otherwise =

y

Все функции определены в декларативном стиле. Тип Ordering кодирует результат операции сравнения.

Два числа могут быть либо равны (значение EQ), либо первое меньше второго (значение LT), либо первое

больше второго (значение GT).

Обратите внимание на функцию compare. Мы не пишем дословное определение значений типа Ordering:

compare x y

| x == y

=

EQ

| x <

y

=

LT

| x >

y

=

GT

Какой стиль лучше? | 67

В этом случае функция compare была бы определена через две других функции класса Ord, а именно

больше > и меньше < . Мы же хотим минимизировать число функций в этом определении. Поэтому вместо

этого определения мы полагаемся на очерёдность обхода альтернатив в охранном выражении.

Если первый случай не прошёл, то во втором случае нет разницы между функциями < и <=. А если не

прошёл и этот случай, то остаётся только вернуть значение GT. Так мы определили функцию compare через

одну функцию класса Ord.

Теперь посмотрим на несколько полезных функций для списков. Посмотрим на три основные функции

для списков, одна из них возможно вам уже порядком поднадоела:

-- Преобразование списка

map :: (a -> b) -> [a] -> [b]

map f []

= []

map f (x:xs) = f x : map f xs

-- Фильтрация списка

filter :: (a -> Bool) -> [a] -> [a]

filter p []

= []

filter p (x:xs) | p x

= x : filter p xs

| otherwise = filter p xs

-- Свёртка списка

foldr

:: (a -> b -> b) -> b -> [a] -> b

foldr f z []

=

z

foldr f z (x:xs) =

f x (foldr f z xs)

Приведём несколько примеров для функции foldr:

and, or :: [Bool] -> Bool

and = foldr (&& ) True

or

= foldr (||) False

(++) :: [a] -> [a] -> [a]

[]

++ ys = ys

(x:xs) ++ ys = x : (xs ++ ys)

concat :: [[a]] -> [a]

concat = foldr (++) []

Функции and и or выполняют логические операции на списках. Так каждый конструктор (:) заменяется

на соответствующую логическую операцию, а пустой список заменяется на значение, которое не влияет на

результат выполнения данной логической операции. Имеется ввиду, что функции (&& True) и (|| False)

дают тот же результат, что и функция id x = x. Функция (++) объединяет два списка, а функция concat


Рекомендуем почитать
Уголовное право. Особенная часть

В книге кратко изложены ответы на основные вопросы темы «Уголовное право. Особенная часть». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Уголовно-исполнительное право

В книге кратко изложены ответы на основные вопросы темы «Уголовно-исполнительное право». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Самоучитель Adobe Premiere 6.5

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


Финансовое право

В учебном пособии в краткой и доступной форме рассмотрены все основные вопросы, предусмотренные государственным образовательным стандартом и учебной программой по дисциплине «Финансовое право».Книга позволит быстро получить основные знания по предмету, а также качественно подготовиться к зачету и экзамену.Рекомендуется студентам, аспирантам и преподавателям по юридическим, экономическим и управленческим специальностям, а также сотрудникам банков.Автор книги, Шевчук Денис Александрович, имеет опыт преподавания различных дисциплин в ведущих ВУЗах Москвы (экономические, юридические, технические, гуманитарные), два высших образования (экономическое и юридическое), более 30 публикаций (статьи и книги), Член Союза Юристов Москвы, Член Союза Журналистов России, Член Союза Журналистов Москвы, Стипендиат Правительства РФ, опыт работы в банках, коммерческих и государственных структурах (в т.ч.


фгос  ответы

Содержащиеся в пособии контрольно-измерительные материалы (КИМы) для 5 класса, аналогичные материалам ЕГЭ, составлены в соответствии с программой общеобразовательных учреждений по русскому языку и учитывают возрастные особенности учащихся. В конце пособия даны ответы на все варианты тестов, предложены диктанты различных типов.Пособие адресовано учителям, ученикам, их родителям и всем, кому необходимо закрепить и систематизировать знания перед ЕГЭ.


Теория литературы. Чтение как творчество

Цель предлагаемого пособия – систематизировать и обогатить представления о природе, структуре и особенностях художественной литературы как вида искусства, помочь совершенствованию читательского мастерства. Книга снабжена кратким словарем основных литературоведческих понятий и терминов (составлен при участии доцента О.В. Быстровой).Для студентов филологических факультетов, учителей, преподавателей литературы высших и средних учебных заведений.