Миран Липовача - Изучай Haskell во имя добра!
- Название:Изучай Haskell во имя добра!
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2012
- Город:Москва
- ISBN:978-5-94074-749-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Миран Липовача - Изучай Haskell во имя добра! краткое содержание
Язык Haskell имеет множество впечатляющих возможностей, но главное его свойство в том, что меняется не только способ написания кода, но и сам способ размышления о проблемах и возможных решениях. Этим Haskell действительно отличается от большинства языков программирования. С его помощью мир можно представить и описать нестандартным образом. И поскольку Haskell предлагает совершенно новые способы размышления о проблемах, изучение этого языка может изменить и стиль программирования на всех прочих.
Ещё одно необычное свойство Haskell состоит в том, что в этом языке придаётся особое значение рассуждениям о типах данных. Как следствие, вы помещаете больше внимания и меньше кода в ваши программы.
Вне зависимости от того, в каком направлении вы намерены двигаться, путешествуя в мире программирования, небольшой заход в страну Haskell себя оправдает. А если вы решите там остаться, то наверняка найдёте чем заняться и чему поучиться!
Эта книга поможет многим читателям найти свой путь к Haskell.
Отображения, монады, моноиды и другое! Всё сказано в названии: «Изучай Хаскель во имя добра!» – весёлый иллюстрированный самоучитель по этому сложному функциональному языку.
С помощью оригинальных рисунков автора, отсылке к поп-культуре, и, самое главное, благодаря полезным примерам кода, эта книга обучает основам функционального программирования так, как вы никогда не смогли бы себе представить.
Вы начнете изучение с простого материала: основы синтаксиса, рекурсия, типы и классы типов. Затем, когда вы преуспеете в основах, начнется настоящий мастер-класс от профессионала: вы изучите, как использовать аппликативные функторы, монады, застежки, и другие легендарные конструкции Хаскеля, о которых вы читали только в сказках.
Продираясь сквозь образные (и порой безумные) примеры автора, вы научитесь:
• Смеяться в лицо побочным эффектам, поскольку вы овладеете техниками чистого функционального программирования.
• Использовать волшебство «ленивости» Хаскеля для игры с бесконечными наборами данных.
• Организовывать свои программы, создавая собственные типы, классы типов и модули.
• Использовать элегантную систему ввода-вывода Хаскеля, чтобы делиться гениальностью ваших программ с окружающим миром.
Нет лучшего способа изучить этот мощный язык, чем чтение «Изучай Хаскель во имя добра!», кроме, разве что, поедания мозга его создателей. Миран Липовача (Miran Lipovača) изучает информатику в Любляне (Словения). Помимо его любви к Хаскелю, ему нравится заниматься боксом, играть на бас-гитаре и, конечно же, рисовать. У него есть увлечение танцующими скелетами и числом 71, а когда он проходит через автоматические двери, он притворяется, что на самом деле открывает их силой своей мысли.
Изучай Haskell во имя добра! - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
ghci> (*) <$> Just 2 <*> Just 8
Just 16
ghci> (++) <$> Just "клингон" <*> Nothing
Nothing
ghci> (-) <$> [3,4] <*> [1,2,3]
[2,1,0,3,2,1]
Поэтому теперь, когда мы рассматриваем их как аппликативные значения, значения типа Maybe a
представляют вычисления, которые могли окончиться неуспешно, значения типа [a]
– вычисления, которые содержат несколько результатов (недетерминированные вычисления), значения типа IO a
– вычисления, которые имеют побочные эффекты, и т. д.
Монады являются естественным продолжением аппликативных функторов и предоставляют решение для следующей проблемы: если у нас есть значение с контекстом типа m a
, как нам применить к нему функцию, которая принимает обычное значение a
и возвращает значение с контекстом? Другими словами, как нам применить функцию типа a –> m b
к значению типа m a
? По существу, нам нужна вот эта функция:
(>>=) :: (Monad m) => m a –> (a –> m b) –> m b
Если у нас есть причудливое значение и функция, которая принимает обычное значение, но возвращает причудливое, как нам передать это причудливое значение в данную функцию? Это является основной задачей при работе с монадами. Мы пишем m
a
вместо f
a
, потому что m
означает Monad
; но монады являются всего лишь аппликативными функторами, которые поддерживают операцию >>=
. Функция >>=
называется связыванием .
Когда у нас есть обычное значение типа a
и обычная функция типа a
–>
b
, передать значение функции легче лёгкого: мы применяем функцию к значению как обычно – вот и всё! Но когда мы имеем дело со значениями, находящимися в определённом контексте, нужно немного поразмыслить, чтобы понять, как эти причудливые значения передаются функциям и как учесть их поведение. Впрочем, вы сами убедитесь, что это так же просто, как раз, два, три.
Приступаем к типу Maybe
Теперь, когда у вас появилось хотя бы смутное представление о том, что такое монады, давайте внесём в это представление несколько большую определённость. К великому удивлению, тип Maybe
является монадой. Здесь мы исследуем её чуть лучше, чтобы понять, как она работает в этой роли.
ПРИМЕЧАНИЕ.Убедитесь, что вы в настоящий момент понимаете, что такое аппликативные функторы (мы обсуждали их в главе 11). Вы должны хорошо разбираться в том, как работают различные экземпляры класса Applicative
и какие виды вычислений они представляют. Для понимания монад вам понадобится развить уже имеющиеся знания об аппликативных функторах.
Значение типа Maybe a
представляет значение типа a
, но с прикреплённым контекстом возможной неудачи в вычислениях. Значение Just "дхарма"
означает, что в нём имеется строка "дхарма"
. Значение Nothing
представляет отсутствие значения, или, если вы посмотрите на строку как на результат вычисления, это говорит о том, что вычисление завершилось неуспешно.

Когда мы рассматривали тип Maybe
как функтор, мы видели, что если нам нужно отобразить его с помощью функции, используя метод fmap
, функция отображала содержимое, если это значение Just
. В противном случае сохранялось значение Nothing
, поскольку с помощью функции нечего отображать!
ghci> fmap (++"!") (Just "мудрость")
Just "мудрость!"
ghci> fmap (++"!") Nothing
Nothing
Тип Maybe
функционирует в качестве аппликативного функтора аналогично. Однако при использовании аппликативных функторов сама функция находится в контексте наряду со значением, к которому она применяется. Тип Maybe
является аппликативным функтором таким образом, что когда мы используем операцию <*>
для применения функции внутри типа Maybe
к значению, которое находится внутри типа Maybe
, они оба должны быть значениями Just
, чтобы результатом было значение Just
; в противном случае результатом будет значение Nothing
. Это имеет смысл. Если недостаёт функции либо значения, к которому вы её применяете, вы не можете ничего получить «из воздуха», поэтому вы должны распространить неудачу.
ghci> Just (+3) <*> Just 3
Just 6
ghci> Nothing <*> Just "алчность"
Nothing
ghci> Justord <*> Nothing
Nothing
Использование аппликативного стиля, чтобы обычные функции работали со значениями типа Maybe
, действует аналогичным образом. Все значения должны быть значениями Just
; в противном случае всё это напрасно ( Nothing
)!
ghci> max <$> Just 3 <*> Just 6
Just 6
ghci> max <$> Just 3 <*> Nothing
Nothing
А теперь давайте подумаем над тем, как бы мы использовали операцию >>=
с типом Maybe
. Операция >>=
принимает монадическое значение и функцию, которая принимает обычное значение. Она возвращает монадическое значение и умудряется применить эту функцию к монадическому значению. Как она это делает, если функция принимает обычное значение? Ну, она должна принимать во внимание контекст этого монадического значения.
В данном случае операция >>=
принимала бы значение типа Maybe a
и функцию типа a –> Maybe b
и каким-то образом применяла бы эту функцию к значению Maybe a
. Чтобы понять, как она это делает, мы будем исходить из того, что тип Maybe
является аппликативным функтором. Скажем, у нас есть анонимная функция \x –> Just (x+1)
. Она принимает число, прибавляет к нему 1
и оборачивает его в конструктор Just
:
ghci> (\x –> Just (x+1)) 1
Just 2
ghci> (\x –> Just (x+1)) 100
Just 101
Если мы передадим ей значение 1
, она вернёт результат Just 2
. Если мы дадим ей значение 100
, результатом будет Just 101
. Это выглядит очень просто. Но как нам передать этой функции значение типа Maybe
? Если мы подумаем о том, как тип Maybe
работает в качестве аппликативного функтора, ответить на этот вопрос будет довольно легко. Мы передаём функции значение Just
, берём то, что находится внутри конструктора Just
, и применяем к этому функцию. Если мы даём ей значение Nothing
, то у нас остаётся функция, но к ней нечего ( Nothing
) применить. В этом случае давайте сделаем то же, что мы делали и прежде, и скажем, что результат равен Nothing
.
Вместо того чтобы назвать функцию >>=
, давайте пока назовём её applyMaybe
. Она принимает значение типа Maybe a
и функцию, которая возвращает значение типа Maybe b
, и умудряется применить эту функцию к значению типа Maybe a
. Вот она в исходном коде:
Интервал:
Закладка: