Миран Липовача - Изучай Haskell во имя добра!
- Название:Изучай Haskell во имя добра!
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2012
- Город:Москва
- ISBN:978-5-94074-749-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Миран Липовача - Изучай Haskell во имя добра! краткое содержание
Язык Haskell имеет множество впечатляющих возможностей, но главное его свойство в том, что меняется не только способ написания кода, но и сам способ размышления о проблемах и возможных решениях. Этим Haskell действительно отличается от большинства языков программирования. С его помощью мир можно представить и описать нестандартным образом. И поскольку Haskell предлагает совершенно новые способы размышления о проблемах, изучение этого языка может изменить и стиль программирования на всех прочих.
Ещё одно необычное свойство Haskell состоит в том, что в этом языке придаётся особое значение рассуждениям о типах данных. Как следствие, вы помещаете больше внимания и меньше кода в ваши программы.
Вне зависимости от того, в каком направлении вы намерены двигаться, путешествуя в мире программирования, небольшой заход в страну Haskell себя оправдает. А если вы решите там остаться, то наверняка найдёте чем заняться и чему поучиться!
Эта книга поможет многим читателям найти свой путь к Haskell.
Отображения, монады, моноиды и другое! Всё сказано в названии: «Изучай Хаскель во имя добра!» – весёлый иллюстрированный самоучитель по этому сложному функциональному языку.
С помощью оригинальных рисунков автора, отсылке к поп-культуре, и, самое главное, благодаря полезным примерам кода, эта книга обучает основам функционального программирования так, как вы никогда не смогли бы себе представить.
Вы начнете изучение с простого материала: основы синтаксиса, рекурсия, типы и классы типов. Затем, когда вы преуспеете в основах, начнется настоящий мастер-класс от профессионала: вы изучите, как использовать аппликативные функторы, монады, застежки, и другие легендарные конструкции Хаскеля, о которых вы читали только в сказках.
Продираясь сквозь образные (и порой безумные) примеры автора, вы научитесь:
• Смеяться в лицо побочным эффектам, поскольку вы овладеете техниками чистого функционального программирования.
• Использовать волшебство «ленивости» Хаскеля для игры с бесконечными наборами данных.
• Организовывать свои программы, создавая собственные типы, классы типов и модули.
• Использовать элегантную систему ввода-вывода Хаскеля, чтобы делиться гениальностью ваших программ с окружающим миром.
Нет лучшего способа изучить этот мощный язык, чем чтение «Изучай Хаскель во имя добра!», кроме, разве что, поедания мозга его создателей. Миран Липовача (Miran Lipovača) изучает информатику в Любляне (Словения). Помимо его любви к Хаскелю, ему нравится заниматься боксом, играть на бас-гитаре и, конечно же, рисовать. У него есть увлечение танцующими скелетами и числом 71, а когда он проходит через автоматические двери, он притворяется, что на самом деле открывает их силой своей мысли.
Изучай Haskell во имя добра! - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
В этой главе мы в общих чертах ознакомились с монадами и изучили, как работают монада Maybe
и списковая монада. В следующей главе мы рассмотрим целую кучу других крутых монад, а также создадим нашу собственную.
14
Ещё немного монад
Мы видели, как монады могут быть использованы для получения значений с контекстами и применения их к функциям и как использование оператора >>=
или нотации do
позволяет нам сфокусироваться на самих значениях, в то время как контекст обрабатывается за нас.

Мы познакомились с монадой Maybe
и увидели, как она добавляет к значениям контекст возможного неуспеха в вычислениях. Мы узнали о списковой монаде и увидели, как легко она позволяет нам вносить недетерминированность в наши программы. Мы также научились работать в монаде IO
даже до того, как вообще выяснили, что такое монада!
В этой главе мы узнаем ещё о нескольких монадах. Мы увидим, как они могут сделать наши программы понятнее, позволяя нам обрабатывать все типы значений как монадические значения. Исследование ряда примеров также укрепит наше понимание монад.
Все монады, которые нам предстоит рассмотреть, являются частью пакета mtl . В языке Haskell пакетом является совокупность модулей. Пакет mtl идёт в поставке с Haskell Platform, так что он у вас, вероятно, уже есть. Чтобы проверить, так ли это, выполните команду ghc-pkg list
в командной строке. Эта команда покажет, какие пакеты для языка Haskell у вас уже установлены; одним из таких пакетов должен являться mtl , за названием которого следует номер версии.
Writer? Я о ней почти не знаю!
Итак, мы зарядили наш пистолет монадой Maybe
, списковой монадой и монадой IO
. Теперь давайте поместим в патронник монаду Writer
и посмотрим, что произойдёт, когда мы выстрелим ею!
Между тем как Maybe
предназначена для значений с добавленным контекстом неуспешно оканчивающихся вычислений, а список – для недетерминированных вычислений, монада Writer
предусмотрена для значений, к которым присоединено другое значение, ведущее себя наподобие журнала. Монада Writer
позволяет нам производить вычисления, в то же время обеспечивая слияние всех журнальных значений в одно, которое затем присоединяется к результату.
Например, мы могли бы снабдить наши значения строками, которые объясняют, что происходит, возможно, для отладочных целей. Рассмотрите функцию, которая принимает число бандитов в банде и сообщает нам, является ли эта банда крупной. Это очень простая функция:
isBigGang :: Int –> Bool
isBigGang x = x > 9
Ну а что если теперь вместо возвращения значения True
или False
мы хотим, чтобы функция также возвращала строку журнала, которая сообщает, что она сделала? Что ж, мы просто создаём эту строку и возвращаем её наряду с нашим значением Bool
:
isBigGang :: Int –> (Bool, String)
isBigGang x = (x > 9, "Размер банды сравнён с 9.")
Так что теперь вместо того, чтобы просто вернуть значение типа Bool
, мы возвращаем кортеж, первым компонентом которого является само значение, а вторым компонентом – строка, сопутствующая этому значению. Теперь у нашего значения появился некоторый добавленный контекст. Давайте опробуем функцию:
ghci> isBigGang 3
(False,"Размер банды сравнён с 9.")
ghci> isBigGang 30
(True,"Размер банды сравнён с 9.")
Пока всё нормально. Функция isBigGang
принимает нормальное значение и возвращает значение с контекстом. Как мы только что увидели, передача ей нормального значения не составляет сложности. Теперь предположим, что у нас уже есть значение, у которого имеется журнальная запись, присоединённая к нему – такая как (3,
"Небольшая банда.")
– и мы хотим передать его функции isBigGang
. Похоже, перед нами снова встаёт вопрос: если у нас есть функция, которая принимает нормальное значение и возвращает значение с контекстом, как нам взять нормальное значение с контекстом и передать его функции?

Исследуя монаду Maybe
, мы создали функцию applyMaybe
, которая принимала значение типа Maybe a
и функцию типа a –> Maybe b
и передавала это значение Maybe a
в функцию, даже если функция принимает нормальное значение типа a
вместо Maybe a
. Она делала это, следя за контекстом, имеющимся у значений типа Maybe a
, который означает, что эти значения могут быть значениями с неуспехом вычислений. Но внутри функции типа a –> Maybe b
мы могли обрабатывать это значение как нормальное, потому что applyMaybe
(которая позже стала функцией >>=
) проверяла, являлось ли оно значением Nothing
либо значением Just
.
В том же духе давайте создадим функцию, которая принимает значение с присоединённым журналом, то есть значением типа (a,String)
, и функцию типа a –> (b,String)
, и передаёт это значение в функцию. Мы назовём её applyLog
. Однако поскольку значение типа (a,String)
не несёт с собой контекст возможной неудачи, но несёт контекст добавочного значения журнала, функция applyLog
будет обеспечивать сохранность первоначального значения журнала, объединяя его со значением журнала, возвращаемого функцией. Вот реализация этой функции:
applyLog :: (a,String) –> (a –> (b,String)) –> (b,String)
applyLog (x,log) f = let (y,newLog) = f x in (y,log ++ newLog)
Когда у нас есть значение с контекстом и мы хотим передать его функции, то мы обычно пытаемся отделить фактическое значение от контекста, затем пытаемся применить функцию к этому значению, а потом смотрим, сбережён ли контекст. В монаде Maybe
мы проверяли, было ли значение равно Just x
, и если было, мы брали это значение x
и применяли к нему функцию. В данном случае очень просто определить фактическое значение, потому что мы имеем дело с парой, где один компонент является значением, а второй – журналом. Так что сначала мы просто берём значение, то есть x
, и применяем к нему функцию f
. Мы получаем пару (y,newLog)
, где y
является новым результатом, а newLog
– новым журналом. Но если мы вернули это в качестве результата, прежнее значение журнала не было бы включено в результат, так что мы возвращаем пару (y,log ++ newLog)
. Мы используем операцию конкатенации ++
, чтобы добавить новый журнал к прежнему.
Вот функция applyLog
в действии:
ghci> (3, "Небольшая банда.") `applyLog` isBigGang
(False,"Небольшая банда.Размер банды сравнён с 9.")
ghci> (30, "Бешеный взвод.") `applyLog` isBigGang
Интервал:
Закладка: