Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Справочник по языку Haskell

Покупка
Артикул: 615902.02.99
К покупке доступен более свежий выпуск Перейти
Данная книга является первой книгой на русском языке, описывающей набор стандартных библиотек функционального языка программирования Haskell. В первой xасти книги кратко рассматривается синтаксис языка и способы его применения для решения задач. Во второй части описываются стандартные библиотеки языка, входящие в поставки всех современных трансляторов Haskell (GHC, HUGS и др.). Книга станет прекрасным подспорьем для программистов, занимающихся прикладным программированием на языке Haskell, а также для студентов, изучающих функциональное программирование.
Душкин, Р. В. Справочник по языку Haskell : практическое руководство / Р. В. Душкин. - Москва : ДМК Пресс, 2016. - 540 с. - ISBN 978-5-97060-361-1. - Текст : электронный. - URL: https://znanium.com/catalog/product/2012592 (дата обращения: 02.05.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Справочник

по языку Haskell

Душкин Р. В.

Москва, 2016

УДК
004.4

ББК
32.973.26018.2
Д86

Душкин Р. В.

Д86
Справочник по языку Haskell. М.: ДМК Пресс, 540 с., ил.

ISBN 978 5970603611

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

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

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

УДК 004.4
ББК 32.973.26018.2

Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то

ни было форме и какими бы то ни было средствами без письменного разрешения владельцев
авторских прав.

Материал, изложенный в данной книге, многократно проверен. Но, поскольку вероятность

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

© Душкин Р. В., 2007

   ISBN 
© Издание, ДМК Пресс, 2016
978 5970603611


Оглавление

Введение
9

I.
Синтаксис и идиомы языка
11

1. Функции
12

1.1. Общий вид определения функций . . . . . . . . . . . . . . . . . . . .
12

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

1.1.2.
Ветвление
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16

1.1.3.
Замыкания . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17

1.1.4.
Бинарные операции . . . . . . . . . . . . . . . . . . . . . . . .
20

1.2. Технология сопоставления с образцами
. . . . . . . . . . . . . . . .
23

1.2.1.
Образцы вида (n + k) . . . . . . . . . . . . . . . . . . . . . . .
25

1.2.2.
Именованные образцы
. . . . . . . . . . . . . . . . . . . . . .
26

1.2.3.
Ленивые образцы . . . . . . . . . . . . . . . . . . . . . . . . .
27

1.3. Ввод и вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28

1.3.1.
Действия ввода/вывода
. . . . . . . . . . . . . . . . . . . . .
28

1.3.2.
Обработка исключений . . . . . . . . . . . . . . . . . . . . . .
32

1.4. Приёмы программирования . . . . . . . . . . . . . . . . . . . . . . .
34

1.4.1.
Двумерный синтаксис
. . . . . . . . . . . . . . . . . . . . . .
34

1.4.2.
Рекурсия и корекурсия . . . . . . . . . . . . . . . . . . . . . .
35

1.4.3.
Накапливающий параметр и хвостовая рекурсия . . . . . . .
39

1.4.4.
Бесточечная нотация . . . . . . . . . . . . . . . . . . . . . . .
41

1.4.5.
Анонимные функции . . . . . . . . . . . . . . . . . . . . . . .
42

Оглавление

1.4.6.
Охрана . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
44

1.4.7.
Определители списков . . . . . . . . . . . . . . . . . . . . . .
46

2. Типы данных
48

2.1. Базовые типы
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48

2.1.1.
Кортежи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49

2.1.2.
Списки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51

2.2. Кратко об алгебраических типах данных
. . . . . . . . . . . . . . .
53

2.2.1.
Перечисления
. . . . . . . . . . . . . . . . . . . . . . . . . . .
54

2.2.2.
Простые структуры . . . . . . . . . . . . . . . . . . . . . . . .
56

2.2.3.
Именованные поля
. . . . . . . . . . . . . . . . . . . . . . . .
59

2.3. Синонимы типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
61

2.4. Параметрический полиморфизм . . . . . . . . . . . . . . . . . . . . .
63

2.5. Типы функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64

2.5.1.
Функции как программные сущности с типом
. . . . . . . .
64

2.5.2.
Каррирование и частичное применение
. . . . . . . . . . . .
66

2.5.3.
Функции высшего порядка . . . . . . . . . . . . . . . . . . . .
68

3. Классы типов и экземпляры классов
71

3.1. Класс как интерфейс . . . . . . . . . . . . . . . . . . . . . . . . . . .
71

3.2. Контекст и прикладные функции . . . . . . . . . . . . . . . . . . . .
76

3.3. Экземпляр — связь между типом и классом . . . . . . . . . . . . . .
78

3.3.1.
Экземпляры класса Logic . . . . . . . . . . . . . . . . . . . .
80

3.4. Изоморфные типы . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
83

3.4.1.
Определение нескольких экземпляров
для уникальной пары (класс, тип) . . . . . . . . . . . . . . .
85

3.5. Автоматическое построение экземпляров
. . . . . . . . . . . . . . .
86

3.6. Окончательные замечания о системе типов в языке Haskell . . . . .
88

4. Модули
91

4.1. Система модулей
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91

4.1.1.
Экспорт программных сущностей . . . . . . . . . . . . . . . .
92

4.1.2.
Импорт сторонних модулей
. . . . . . . . . . . . . . . . . . .
93

4.2. Абстракция данных при помощи модулей . . . . . . . . . . . . . . .
97

4.3. Кое-что ещё о модулях . . . . . . . . . . . . . . . . . . . . . . . . . .
98

Оглавление
5

5. Сводная информация
100

II.
Стандартные библиотеки
105

6. Стандартный модуль Prelude
108

6.1. Prelude: Алгебраические типы данных
. . . . . . . . . . . . . . . . 108

6.2. Prelude: Классы и их экземпляры
. . . . . . . . . . . . . . . . . . . 115

6.3. Prelude: Функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
6.4. Prelude: Операторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

7. Пакет модулей Control
172

7.1. Модуль Applicative
. . . . . . . . . . . . . . . . . . . . . . . . . . . 172

7.2. Модуль Arrow
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

7.3. Модуль Concurrent . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181

7.3.1.
Модуль Chan . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

7.3.2.
Модуль MVar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

7.3.3.
Модуль QSem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

7.3.4.
Модуль QSemN
. . . . . . . . . . . . . . . . . . . . . . . . . . . 193

7.3.5.
Модуль SampleVar . . . . . . . . . . . . . . . . . . . . . . . . . 194

7.4. Модуль Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
7.5. Модуль Monad
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211

7.5.1.
Модуль Fix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220

7.5.2.
Модуль Instances . . . . . . . . . . . . . . . . . . . . . . . . . 222

7.5.3.
Модуль ST
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

7.6. Модуль Parallel
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

8. Пакет модулей Data
226

8.1. Модуль Array
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226

8.1.1.
Модуль Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

8.1.2.
Модуль Diff . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

8.1.3.
Модуль IArray . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

8.1.4.
Модуль IO
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

8.1.5.
Модуль MArray . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

8.1.6.
Модуль ST
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

8.1.7.
Модуль Storable
. . . . . . . . . . . . . . . . . . . . . . . . . 243

Оглавление

8.1.8.
Модуль Unboxed . . . . . . . . . . . . . . . . . . . . . . . . . . 245

8.2. Модуль Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
8.3. Модуль Bool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
8.4. Модуль ByteString . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248

8.4.1.
Модуль Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277

8.4.2.
Модуль Char8
. . . . . . . . . . . . . . . . . . . . . . . . . . . 286

8.4.3.
Модуль Lazy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

8.5. Модуль Char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
8.6. Модуль Complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
8.7. Модуль Dynamic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
8.8. Модуль Either . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
8.9. Модуль Eq
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303

8.10. Модуль Fixed
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304

8.11. Модуль Foldable
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305

8.12. Модуль Graph
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313

8.13. Модуль HashTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
8.14. Модуль Int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
8.15. Модуль IntMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
8.16. Модуль IntSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
8.17. Модуль IORef
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360

8.18. Модуль Ix
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

8.19. Модуль List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
8.20. Модуль Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
8.21. Модуль Maybe
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383

8.22. Модуль Monoid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
8.23. Модуль Ord . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
8.24. Модуль Ratio
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390

8.25. Модуль Sequence
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390

8.26. Модуль Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
8.27. Модуль STRef
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

8.27.1. Модуль Lazy . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
8.27.2. Модуль Strict . . . . . . . . . . . . . . . . . . . . . . . . . . . 402

8.28. Модуль Traversable
. . . . . . . . . . . . . . . . . . . . . . . . . . . 402

8.29. Модуль Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
8.30. Модуль Tuple
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408

Оглавление
7

8.31. Модуль Typeable
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408

8.32. Модуль Unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
8.33. Модуль Version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
8.34. Модуль Word . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416

9. Пакет модулей Debug
419

9.1. Модуль Trace
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

10.Пакет модулей Foreign
421

10.1. Модуль C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422

10.1.1. Модуль Error
. . . . . . . . . . . . . . . . . . . . . . . . . . . 423

10.1.2. Модуль String . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
10.1.3. Модуль Types
. . . . . . . . . . . . . . . . . . . . . . . . . . . 436

10.2. Модуль ForeignPtr . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
10.3. Модуль Marshal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444

10.3.1. Модуль Alloc
. . . . . . . . . . . . . . . . . . . . . . . . . . . 445

10.3.2. Модуль Array
. . . . . . . . . . . . . . . . . . . . . . . . . . . 447

10.3.3. Модуль Error
. . . . . . . . . . . . . . . . . . . . . . . . . . . 453

10.3.4. Модуль Pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
10.3.5. Модуль Utils
. . . . . . . . . . . . . . . . . . . . . . . . . . . 459

10.4. Модуль Ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
10.5. Модуль StablePtr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
10.6. Модуль Storable
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468

11.Пакет модулей System
471

11.1. Модуль Cmd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
11.2. Модуль CPUTime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
11.3. Модуль Directory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473

11.3.1. Модуль Internals . . . . . . . . . . . . . . . . . . . . . . . . . 482

11.4. Модуль Environment
. . . . . . . . . . . . . . . . . . . . . . . . . . . 482

11.5. Модуль Exit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
11.6. Модуль Info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
11.7. Модуль IO
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 486

11.7.1. Модуль Error
. . . . . . . . . . . . . . . . . . . . . . . . . . . 497

11.7.2. Модуль Unsafe . . . . . . . . . . . . . . . . . . . . . . . . . . . 507

11.8. Модуль Locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507

Оглавление

11.9. Модуль Mem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510

11.9.1. Модуль StableName . . . . . . . . . . . . . . . . . . . . . . . . 510
11.9.2. Модуль Weak . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512

11.10.Модуль Random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
11.11.Модуль Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519

12.Пакет модулей Text
528

12.1. Модуль Printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528
12.2. Модуль Read . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531

12.2.1. Модуль Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533

12.3. Модуль Show . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535

12.3.1. Модуль Functions . . . . . . . . . . . . . . . . . . . . . . . . . 536

Заключение
537

Литература
538

Введение

Язык Haskell является динамично развивающимся функциональным языком

программирования, который получает всё больше и больше сторонников во всём
мире, в том числе и в России. Этот язык вырвался из рамок научных лабораторий 
и стал языком программирования общего назначения. Вместе с тем хорошей
литературы об этом прекрасном языке программирования категорически мало,
тем более на русском языке.

В конце 2006 года из печати вышла первая и на текущий момент (2007 год)

единственная книга на русском языке, рассматривающая функциональное программирование 
на языке Haskell [1]. Несмотря на то что в этой книге тема языка
Haskell раскрыта практически полностью, его описание в ней страдает неполнотой 
и некоторой «поверхностностью». С другой стороны, достаточно серьёзная
математика в книге немного отпугивает неподготовленного читателя. Поэтому
книга явилась своеобразным «первым блином», который необходим для перво-
начального ввода в проблематику. Однако в связи с ростом популярности как
языка Haskell, так и парадигмы функционального программирования, необходи-
мо больше всевозможных материалов, охватывающих различные аспекты и пред-
назначенных для разной целевой аудитории.

Данная книга является кратким справочником по функциональному языку

программирования Haskell стандарта Haskell-98 (без описания многочисленных
расширений языка). В книге собрано описание знаний по успешному применению
языка Haskell на практике. Она предназначена для тех, кто уже знает принципы
функциональной парадигмы и сам язык Haskell. Это связано с тем, что, несмотря
на то что практически всю информацию можно почерпнуть из интернета, очень
часто необходимо иметь под рукой полноценный справочник, в котором мож-

Введение

но быстро найти ответы на специализированные вопросы. И эта книга как раз
и предназначена для подобных целей.

Поскольку книга названа «кратким справочником», одним из принципов, ко-

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

Справочник разбит на две части. В первой части представлено краткое опи-

сание синтаксиса языка Haskell, а также наиболее часто и успешно используемые
техники программирования на нём (ведь не секрет, что в каждом языке имеются
свои особые методы «правильного» программирования). Во второй части опи-
сываются наиболее часто использующиеся стандартные модули, входящие в по-
ставку двух наиболее известных трансляторов языка — HUGS 98 и GHC. Первая
часть разбита на главы, каждая из которых описывает одну из пяти существую-
щих в языке программных сущностей (и дополнительная шестая глава со свод-
ной информацией). Главы второй части соответствуют стандартным библиотекам
языка Haskell.

В целях единообразия представления информации в книге используется спе-

циальное форматирование текста, выделяющее определённые структурные эле-
менты. Так, наименования программных сущностей выделяются моноширинным
шрифтом обычного начертания: head, True, Enum и т. д. В отличие от идентифи-
каторов ключевые слова записываются моноширинным шрифтом с подчёркива-
нием: if, do, instance и т. д. Знаки операций и специальные символы при записи
ограничиваются круглыми скобками, чтобы выделить и отделить знаки от ос-
новного текста: (+), (>=), (‘) и т. д., в то время как сами скобки в случае необхо-
димости записываются в кавычках: «(», «]». Кроме того, наименования модулей,
библиотек и специальных утилит также записываются моноширинным шрифтом:
Prelude, Data.List и пр.

Краткость — сестра таланта, как говаривал русский классик А. П. Чехов.

Поэтому осталось только упомянуть, что автор чрезвычайно благодарен Рога-
нову В. А. за помощь в создании книги, и то, что автор будет рад получить
комментарии и замечания по адресу электронной почты darkus.14@gmail.com.

Часть I.

Синтаксис и идиомы языка

Глава 1.

Функции

Функции являются базовым программным элементом в языке Haskell, при по-

мощи которого строятся программы. Сложно (но можно) построить программу
на этом языке, в которой не было бы определений функций. При помощи функций 
определяются вычислительные процессы, которые являются сутью создаваемой 
программы. Поэтому изучение способов определения функций является
важнейшим делом в постижении языка Haskell.

1.1.
Общий вид определения функций

С точки зрения функционального программирования и языка Haskell функция 
является программной сущностью верхнего уровня, при этом программа может 
состоять только из набора этих сущностей. Остальные программные сущности 
языка Haskell (типы данных, классы и их экземпляры, модули) могут присутствовать, 
а могут и отсутствовать в программах, но функции присутствуют
всегда. Поэтому определение функций является главным при программировании
на языке Haskell.

Как уже сказано, каждое определение функции является декларацией верхнего 
уровня. В определение может входить необязательная сигнатура, то есть
описание типа функции, а также собственно описание того, что функция возвращает 
на основании входных параметров. Тем самым функция в языке Haskell
является отражением математического понятия «функция», которое определе-

1.1. Общий вид определения функций
13

но как некоторая взаимосвязь между входными параметрами (аргументами) и
выходным значением (результатом).

Любые вычислительные процессы в языке Haskell описываются при помощи

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

repeat :: a -> [a]
repeat x = xs

where

xs = x:xs

Это определение функции repeat из стандартного модуля Prelude, которая

строит бесконечный список из переданного ей на вход значения (подробно эта
функция описана на стр. 158). Список состоит из элементов, каждый из которых
равен входному значению. В связи с тем, что язык Haskell является ленивым,
в нём вполне возможны такие объекты, как бесконечные списки.

Данное определение читается достаточно просто. Первая строка как раз яв-

ляется сигнатурой, которая описывает тип функции (подробное описание типов
функций приводится в разделе 2.5.). Запись в этом примере обозначает, что функ-
ция repeat получает на вход ровно один аргумент некоторого типа a, а возвраща-
ет значение типа [a], то есть список значений типа a. Вторая строка определя-
ет способ вычисления результата, возвращаемого функцией. Здесь используется
локальное определение («замыкание») xs, которое описывается ниже после клю-
чевого слова where. Само замыкание xs равно входному параметру x, который
при помощи конструктора списков (:) добавляется к тому же xs. То есть здесь
используется рекурсия, которая никогда не остановится, чем и достигается бес-
конечность получаемого результата.

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

Каждое определение функции (не сигнатура) состоит из набора так называ-

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

Глава 1. Функции

пробелами. Более детально образцы и клозы описываются чуть ниже (см. раз-
дел 1.2.). Здесь же детально описывается несколько примеров определения раз-
личных функций, которые взяты всё из того же стандартного модуля Prelude.

Определение любой функции может состоять из одного клоза. Следующим

образом, к примеру, определены функции для работы с парами, являющими со-
бой кортежи из двух элементов (подробно кортежи описываются в главе 2.):

fst (x, _) = x

snd (_, y) = y

Как видно, обе функции принимают на вход один параметр, который являет-

ся парой: оба значения пары заключены в скобки и разделены запятой. Первая
функция возвращает первый элемент пары, вторая — второй соответственно.
Формальный входной параметр функций записан в виде образца, в котором ис-
пользуется маска подстановки (_) вместо тех параметров, которые не использу-
ются в теле функции. Так, функция fst оперирует только первым элементом
пары, поэтому второй можно заменить маской (_). Впрочем, ничто не мешает
пользоваться и полноценными образцами:

fst (x, y) = x

Такое определение полностью тождественно тому, что было приведено ра-

нее. Однако хорошим тоном является замена неиспользующихся образцов имен-
но символом (_). В разделе 1.2. маска подстановки описана более подробно. Сами
приведённые функции подробно описываются на стр. 136 и стр. 163 соответствен-
но.

Различных образцов в клозе функции может быть несколько. Их количество

может соответствовать числу формальных параметров функции или быть мень-
ше, но не больше (большее количество образцов просто обозначает, что функция
принимает на вход большее число параметров, при этом в сигнатуре функции,
если она приводится, должен быть описан тип каждого входного параметра). Вот
примеры функций с двумя и тремя образцами (эти функции детально рассмат-
риваются на стр. 129 и стр. 133 соответственно):

const k _ = k

1.1. Общий вид определения функций
15

flip f x y = f y x

Все рассмотренные примеры имеют в определении один клоз, то есть одно

выражение, определяющее значение функции. В функциональном программиро-
вании принято, что функция может быть определена несколькими клозами, каж-
дый из которых характеризуется определённым набором образцов. Например,
вот функции для оперирования со списками — их определения состоят из двух
клозов:

last [x]
= x

last (_:xs) = last xs

init [x]
= []

init (x:xs) = x : init xs

Первая функция возвращает последний элемент заданного списка (детально

рассматривается на стр. 251), вторая — все начальные элементы списка, кроме
последнего (детально рассматривается на стр. 137).

Использование нескольких клозов в определении функции является есте-

ственным способом ветвления алгоритма в функциональном программировании.
При этом в разных языках функционального программирования используется
различный способ обработки клозов. В языке Haskell весьма важен порядок кло-
зов, так как транслятор просматривает набор клозов сверху вниз и выбирает
среди них первый, чьи образцы подходят под фактические параметры функции,
переданные ей на вход при вызове.

Так, в указанных выше функциях last и init на вход приходит некий спи-

сок, в котором должен быть по крайней мере один элемент. В случае если список
состоит из одного элемента, «срабатывает» первый клоз. Если список состоит
из более чем одного элемента, транслятор пропускает первый клоз и выбира-
ет второй. Если бы клозы в этих функциях стояли наоборот, то первый клоз
срабатывал бы на любом непустом списке, в том числе и на таком, в котором
содержится один элемент (поскольку на самом деле в нём содержится пара этого
элемента и пустого списка). Поэтому программист всегда должен внимательно
следить за порядком расположения клозов в языке Haskell.

Глава 1. Функции

1.1.2.
Ветвление

Несколько клозов — не единственный способ организации ветвления вычислительного 
процесса в языке Haskell. В нём присутствуют и «традиционные»
способы ветвления, а именно оператор if и оператор case.

Оператор if

Оператор if предназначен для ветвления вычислительного процесса в зависимости 
от условия булевского типа. Обычно этот оператор представляется в виде
if-then-else, где после ключевого слова if идёт условие ветвления, после слова 
then следует выражение, которое выполняется в случае истинности условия;
а после ключевого слова else находится выражение, которое выполняется в случае 
ложности условия. В языке Haskell обе части then и else обязательны при использовании 
оператора if, так как они определяют не действия в порядке некоторого 
вычисления, а функции, которые возвращают результат.

Выражения в обеих частях условного оператора then и else должны иметь

один и тот же тип, который равен типу, возвращаемому функцией. Это очень
важное условие использования этого ключевого слова. В качестве примера использования 
оператора if в языке Haskell можно привести функцию until
из стандартного модуля Prelude (описывается на стр. 167):

until p f x = if p x

then x
else until p f (f x)

Эта функция предназначена для организации циклического применения

функции f к аргументу, начальным значением которого является x. Цикл останавливается, 
когда предикат p становится равным True на очередном значении,
которое возвратила функция f.

Оператор case

Оператор case предназначен для множественного ветвления, когда вычислительный 
процесс разбивается на несколько ветвей в зависимости от значения выражения 
произвольного типа. Оператор if является частным случаем оператора
case, и, в принципе, любое ветвление можно было бы организовывать при помощи

К покупке доступен более свежий выпуск Перейти