Справочник по языку Haskell
Покупка
Тематика:
Программирование и алгоритмизация
Издательство:
ДМК Пресс
Автор:
Душкин Роман Викторович
Год издания: 2009
Кол-во страниц: 544
Дополнительно
Вид издания:
Практическое пособие
Уровень образования:
ВО - Бакалавриат
ISBN: 5-94074-410-9
Артикул: 615902.01.99
К покупке доступен более свежий выпуск
Перейти
Данная книга является первой книгой на русском языке, описывающей набор стандартных библиотек функционального языка программирования Haskell. В первой xасти книги кратко рассматривается синтаксис языка и способы его применения для решения задач. Во второй части описываются стандартные библиотеки языка, входящие в поставки всех современных трансляторов Haskell (GHC, HUGS и др.). Книга станет прекрасным подспорьем для программистов, занимающихся прикладным программированием на языке Haskell, а также для студентов, изучающих функциональное программирование.
Тематика:
ББК:
УДК:
ОКСО:
- ВО - Бакалавриат
- 09.03.01: Информатика и вычислительная техника
- 09.03.02: Информационные системы и технологии
- 09.03.03: Прикладная информатика
ГРНТИ:
Скопировать запись
Фрагмент текстового слоя документа размещен для индексирующих роботов.
Для полноценной работы с документом, пожалуйста, перейдите в
ридер.
Справочник по языку Haskell Душкин Р. В. Москва
УДК 004.4 ББК 32.973.26018.2 Д86 Душкин Р. В. Д86 Справочник по языку Haskell. М.: ДМК Пресс, 544 с., ил. ISBN 5940744109 Данная книга является первой книгой на русском языке, описывающей набор стандартных библиотек функционального языка программирования Haskell. В первой xасти книги кратко рассматривается синтаксис языка и способы его применения для решения задач. Во второй части описываются стандартные библиотеки языка, входящие в поставки всех современных трансляторов Haskell (GHC, HUGS и др.). Книга станет прекрасным подспорьем для программистов, занимающихся прикладным программированием на языке Haskell, а также для студентов, изучающих функциональное программирование. УДК 004.4 ББК 32.973.26018.2 Все права защищены. Любая часть этой книги не может быть воспроизведена в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Материал, изложенный в данной книге, многократно проверен. Но, поскольку вероятность технических ошибок все равно существует, издательство не может гарантировать абсолютную точность и правильность приводимых сведений. В связи с этим издательство не несет ответственности за возможные ошибки, связанные с использованием книги. © Душкин Р. В. ISBN 594074© Оформление ДМК Пресс 410 9
Оглавление Введение 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, и, в принципе, любое ветвление можно было бы организовывать при помощи
К покупке доступен более свежий выпуск
Перейти