ebook img

Изучаем Haskell PDF

464 Pages·2015·7.317 MB·Russian
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Изучаем Haskell

Alejandro Serrano Mena Beginning Haskell: A Project-Based Approach Алехандро Серано Мена ИЗУЧАЕМ HASKELL А. Мена Изучаем Haskell. Библиотека программиста Серия «Библиотека программиста» Перевел с английского Н. Вильчинский Заведующий редакцией П. Щеголев Ведущий редактор Ю. Сергиенко Литературный редактор А. Жданов Художник В. Шимкевич Корректор С. Беляева, Н. Викторова Верстка Л. Соловьева ББК 32.973.2-018.1 УДК 004.43 Мена А. М45 Изучаем Haskell. Библиотека программиста. — СПб.: Питер, 2015. — 464 с.: ил. — (Серия «Библиотека программиста»). ISBN 978-5-496-01188-4 Эта книга поможет вам быстро освоить базовые концепции языка программирования Haskell, его библиотеки и компоненты, а также заложит основы функциональной парадигмы программирования, ко- торая становится все более значимой в современном мире разработки ПО. Книга предлагает проектный подход к освоению материала, используя в качестве прототипа проект реализации интернет-магазина. Здесь рассматривается экосистема языка Haskell и его вспомогательных средств, инструменты Cabal для управление проектами, модули HUnit и QuickCheck для тестирования программ, фреймворк Scotty для разработки веб-приложений, Persistent и Esqueleto — для управления базами данных и многие другие компоненты и библиотеки Haskell. 12+ (В соответствии с Федеральным законом от 29 декабря 2010 г. № 436-ФЗ.) ISBN 978-1430262503 англ. © Apress ISBN 978-5-496-01188-4 © Перевод на русский язык ООО Издательство «Питер», 2015 © Издание на русском языке, оформление ООО Издательство «Питер», 2015 Права на издание получены по соглашению с Apress. Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав. Информация, содержащаяся в данной книге, получена из источников, рассматриваемых издательством как на- дежные. Тем не менее, имея в виду возможные человеческие или технические ошибки, издательство не может гарантировать абсолютную точность и полноту приводимых сведений и не несет ответственности за возможные ошибки, связанные с использованием книги. ООО «Питер Пресс», 192102, Санкт-Петербург, ул. Андреевская (д. Волкова), д. 3, литер А, пом. 7Н. Налоговая льгота — общероссийский классификатор продукции ОК 034-2014, 58.11.12.000 — Книги печатные профессиональные, технические и научные. Подписано в печать 28.10.14. Формат 70×100/16. Усл. п. л. 37,410. Тираж 1000. Заказ 0000. Отпечатано в полном соответствии с качеством предоставленных издательством материалов в ГППО «Псковская областная типография». 180004, Псков, ул. Ротная, 34. Оглавление Об авторе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 О научном редакторе . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Благодарности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Введение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Зачем изучать функциональное программирование . . . . . . . . . . . . . 11 Почему вам нужна эта книга . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Часть I . Первые шаги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Глава 1 . Настоящий функциональный язык . . . . . . . . . . . . . . . . . 14 Почему именно Haskell? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 История Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Ваша рабочая среда . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Первые шаги в использовании GHCi . . . . . . . . . . . . . . . . . . . . . . . . . 24 Магазин, продающий машины времени . . . . . . . . . . . . . . . . . . . . . . 26 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Глава 2 . Объявление модели данных . . . . . . . . . . . . . . . . . . . . . . . 28 Работа с символами, числами и списками . . . . . . . . . . . . . . . . . . . . . 28 Создание нового проекта . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Определение простых функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Работа с типами данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Сопоставление с образцом . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Записи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Глава 3 . Многократное использование кода с помощью списков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Параметрический полиморфизм . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Функции в качестве аргументов . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Подробнее о модулях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Углубленное изучение списков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Формирователи списков . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 6 Оглавление Haskell-оригами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Глава 4 . Контейнеры и классы типов . . . . . . . . . . . . . . . . . . . . . . 100 Использование пакетов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Контейнеры: проекции, множества, деревья и графы . . . . . . . . . . . 108 Специальный полиморфизм: классы типов . . . . . . . . . . . . . . . . . . . 120 Двоичные деревья для минимальной цены . . . . . . . . . . . . . . . . . . . 129 Классы типов, связанные с контейнерами . . . . . . . . . . . . . . . . . . . 134 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Глава 5 . Лень и бесконечные структуры . . . . . . . . . . . . . . . . . . . 139 Бесконечное количество машин времени . . . . . . . . . . . . . . . . . . . . 139 Модель ленивых вычислений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Профилирование с помощью GHC . . . . . . . . . . . . . . . . . . . . . . . . . 152 Строгие аннотации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Часть II . Анализ данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Глава 6 . Ознакомление с клиентами с помощью монад . . . . . . . 162 Анализ данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Исследование монад . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Различные виды состояний . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Глава 7 . Другие рекомендуемые монады . . . . . . . . . . . . . . . . . . . 194 Возвращение более одного значения . . . . . . . . . . . . . . . . . . . . . . . 194 Неудачи и альтернативы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Вывод ассоциативных правил . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Задачи поиска . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Монада Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Возрождение монад и списков . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 Глава 8 . Использование нескольких ядер . . . . . . . . . . . . . . . . . . 224 Параллелизм, одновременность, распределенность . . . . . . . . . . . . 224 Монада Par . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Программная транзакционная память . . . . . . . . . . . . . . . . . . . . . . . 232 Облачные решения для Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 Оглавление 7 Часть III . Использование ресурсов . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Глава 9 . Работа с файлами: ввод-вывод и библиотека conduit 250 Базовые ввод и вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 Случайность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 Работа с файлами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Обработка ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Потоковый ввод-вывод данных с помощью библиотеки conduit . . . . 270 За пределами текстовых файлов . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 Глава 10 . Создание и синтаксический разбор текста . . . . . . . . . 282 Пять текстовых типов данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Создание текста со скоростью ветра . . . . . . . . . . . . . . . . . . . . . . . 287 Синтаксический разбор с использованием пакета attoparsec . . . . . . 290 Представление новых классов типов . . . . . . . . . . . . . . . . . . . . . . . 296 Не нужно излишеств: используйте формат JSON . . . . . . . . . . . . . . 304 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 Глава 11 . Безопасный доступ к базам данных . . . . . . . . . . . . . . . 311 Средства доступа к базам данных . . . . . . . . . . . . . . . . . . . . . . . . . 311 Соединение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Схемы и переносы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 Запросы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 Вставка, обновление и удаление . . . . . . . . . . . . . . . . . . . . . . . . . . 330 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Глава 12 . Веб-приложения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Веб-экосистема Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Структура RESTful . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338 Разработка внутреннего интерфейса в среде Scotty . . . . . . . . . . . . 339 Разработка внешнего интерфейса с помощью компилятора Fay . . . 349 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 Часть IV . Предметно-ориентированные языки . . . . . . . . . . . . . . . . . 355 Глава 13 . Строгие типы для описания предложений . . . . . . . . . 356 Предметно-ориентированные языки . . . . . . . . . . . . . . . . . . . . . . . . 356 Безопасность языка выражений . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Зависимая типизация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Программирование на уровне типов в Haskell . . . . . . . . . . . . . . . . . 370 Функциональные зависимости . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373 8 Оглавление Семейства типов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379 Продвижение типа и одноэлементные типы . . . . . . . . . . . . . . . . . . 385 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394 Глава 14 . Интерпретация предложений с помощью атрибутов 395 Варианты интерпретации и атрибутивные грамматики . . . . . . . . . . 395 Наша первая атрибутивная грамматика . . . . . . . . . . . . . . . . . . . . . 398 Интеграция UUAGC-кода в пакет . . . . . . . . . . . . . . . . . . . . . . . . . . 401 Интерпретация выражений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 Варианты интерпретации предложений . . . . . . . . . . . . . . . . . . . . . 409 Оригами-программирование для любого типа данных . . . . . . . . . . 415 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 Часть V . Инжиниринг магазина . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 Глава 15 . Документирование, тестирование и проверка . . . . . . 420 Документирование двоичных деревьев с помощью утилиты Haddock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421 Блочное тестирование с помощью утилиты HUnit . . . . . . . . . . . . . . 424 Рандомизированное тестирование с помощью библиотеки QuickCheck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430 Формальная верификация с использованием языка Idris . . . . . . . . . 434 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438 Глава 16 . Создание архитектуры приложения . . . . . . . . . . . . . . 439 Паттерны проектирования и функциональное программирование . . 439 Рекомендации среднего порядка . . . . . . . . . . . . . . . . . . . . . . . . . . 441 Утилиты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443 Проекты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 Выводы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 Приложение А . Дальнейшие перспективы . . . . . . . . . . . . . . . . . . 459 Haskell-ресурсы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460 Приложение Б . Путешествие во времени с Haskell . . . . . . . . . . . 462 Об авторе Алехандро Серано Мена — горячий сторонник функционального программирова- ния, он использует Haskell для личных и коммерческих проектов уже более пяти лет. В настоящее время пишет кандидатскую диссертацию в Утрехтском универ- ситете. Область его интересов связана с разработкой систем со строгой типизацией и взаимодействием с такими системами, например, посредством языка Haskell. Он внес вклад в ряд проектов с открытым кодом, включая Mono и Nemerle. В 2011 году принял участие в программе Google Summer of Code, совершенствуя подключаемый Haskell-модуль EclipseFP для популярной среды разработки Eclipse. В 2012 году он с двумя друзьями основал компанию Nublic, деятельность которой сконцентрирована на предоставлении облачных инструментов для до- машних сред. Основная часть программного обеспечения данного проекта была создана с использованием языка Scala, сочетающего объектно-ориентированные и функциональные аспекты. Диплом по информатике и математике Алехандро получил в родном Мадридском университете. В период обучения он активно продвигал среди студентов идеи свободного программного обеспечения и функциональной парадигмы. Его статьи можно прочитать в испанском журнале «Todo Programación». О научном редакторе Жан-Филипп Моресмо пишет программы уже пятнадцать лет. Он занимался созданием веб-приложений с 1996 года и всегда испытывал интерес к интегриро- ванным средам разработки и анализу языка. Он принимает активное участие в работе сообщества по разработке приложений с открытым кодом на языке Haskell, а также входит в группу поддержки проекта EclipseFP. Его блог находится по адресу http://jpmoresmau .blogspot .com. Ж.-Ф. Мо- ресмо с женой и двумя детьми живет на юге Франции. Благодарности Прежде всего, хотел бы отметить грандиозную работу научного редактора и ре- дакции. Их комментарии и предложения представляли исключительную ценность и позволили существенно улучшить качество книги. Еще я хотел бы отдельно от- метить великолепную работу Жана-Филиппа Моресмо над EclipseFP. Написание книги — дело не только благодарное, но и хлопотное. И в те моменты, когда настроение падало до нуля, я всегда ощущал поддержку Елены. Она была со мной и в минуты размышлений, и в минуты оттачивания примеров, и в минуты бесконечных правок текста. Cемья и друзья поддерживали меня все это время, поэтому большое спасибо вам всем. Мои родители, Кармен и Хулиан, заслуживают особого упоминания: они поддерживали меня при выполнении каждого моего проекта, и как бы странно это ни звучало, на протяжении всей моей жизни. Они купили мне первый компьютер, и именно на нем я впервые начал программировать в старой доброй среде Visual Basic. Поэтому хотя бы ради справедливости нужно сказать, что без их помощи вы бы никогда не читали эту книгу. Нельзя не восхититься всем Haskell-сообществом. Наличие обширных подписок на рассылки и групповых чатов, наполненных собеседников (заметьте, умных собеседников!), всегда готовых прийти на помощь, является хорошим стимулом для проявления любопытства и познания нового. Каждая библиотека и каждый компилятор, о которых рассказывается в книге, были с любовью разработаны этим сообществом: именно они сделали Haskell таким великим языком. И в завершение хочу поблагодарить своих преподавателей и коллег из Утрехтско- го университета. Хотя мы были знакомы всего лишь пару месяцев, их страстное увлечение функциональным программированием оказало существенное влияние на книгу.

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.