- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Изучай Haskell во имя добра! - Миран Липовача
Шрифт:
Интервал:
Закладка:
Функция return помещает значение в минимальный контекст, который по-прежнему возвращает это значение в качестве своего результата. Это значит, что, например, для типа Maybe она не вносит никакого неуспеха в вычислениях; для списков – не вносит какую-либо дополнительную недетерминированность.
Вот пробный запуск для нескольких монад:
ghci> Just "двигайся дальше" >>= (x –> return x)
Just "двигайся дальше"
ghci> [1,2,3,4] >>= (x –> return x)
[1,2,3,4]
ghci> putStrLn "Вах!" >>= (x –> return x)
Вах!
В этом примере со списком реализация операции >>= выглядит следующим образом:
xs >>= f = concat (map f xs)
Поэтому когда мы передаём список [1,2,3,4] функции return, сначала она отображает [1,2,3,4], что в результате даёт список списков [[1],[2],[3],[4]]. Затем это конкатенируется, и мы получаем наш изначальный список.
Левое тождество и правое тождество являются, по сути, законами, которые описывают, как должна вести себя функция return. Это важная функция для превращения обычных значений в монадические, и было бы нехорошо, если бы монадическое значение, которое она произвела, имело больше, чем необходимый минимальный контекст.
Ассоциативность
Последний монадический закон говорит, что когда у нас есть цепочка применений монадических функций с помощью операции >>=, не должно иметь значения то, как они вложены. В формальной записи выполнение (m >>= f) >>= g – точно то же, что и выполнение m >>= (x –> f x >>= g).
Гм-м, что теперь тут происходит? У нас есть одно монадическое значение, m, и две монадические функции, f и g. Когда мы выполняем выражение (m >>= f) >>= g, то передаём значение m в функцию f, что даёт в результате монадическое значение. Затем мы передаём это новое монадическое значение функции g. В выражении m >>= (x –> f x >>= g) мы берём монадическое значение и передаём его функции, которая передаёт результат применения f x функции g. Нелегко увидеть, почему обе эти записи равны, так что давайте взглянем на пример, который делает это равенство немного более очевидным.
Помните нашего канатоходца Пьера, который пытался удержать равновесие, в то время как птицы приземлялись на его балансировочный шест? Чтобы симулировать приземление птиц на балансировочный шест, мы создали цепочку из нескольких функций, которые могли вызывать неуспешное окончание вычислений:
ghci> return (0, 0) >>= landRight 2 >>= landLeft 2 >>= landRight 2
Just (2,4)
Мы начали со значения Just (0, 0), а затем связали это значение со следующей монадической функцией landRight 2. Результатом было другое монадическое значение, связанное со следующей монадической функцией, и т. д. Если бы надлежало явно заключить это в скобки, мы написали бы следующее:
ghci> ((return (0, 0) >>= landRight 2) >>= landLeft 2) >>= landRight 2
Just (2,4)
Но мы также можем записать инструкцию вот так:
return (0, 0) >>= (x –>
landRight 2 x >>= (y –>
landLeft 2 y >>= (z –>
landRight 2 z)))
Вызов return (0, 0) – то же самое, что Just (0, 0), и когда мы передаём это анонимной функции, образец x принимает значение (0, 0). Функция landRight принимает количество птиц и шест (кортеж, содержащий числа) – и это то, что ей передаётся. В результате мы имеем значение Just (0, 2), и, когда передаём его следующей анонимной функции, образец y становится равен (0, 2). Это продолжается до тех пор, пока последнее приземление птицы не вернёт в качестве результата значение Just (2, 4), что в действительности является результатом всего выражения.
Поэтому неважно, как у вас вложена передача значений монадическим функциям. Важен их смысл. Давайте рассмотрим ещё один способ реализации этого закона. Предположим, мы производим композицию двух функций, f и g:
(.) :: (b –> c) –> (a –> b) –> (a –> c)
f . g = (x –> f (g x))
Если функция g имеет тип a –> b и функция f имеет тип b –> c, мы компонуем их в новую функцию типа a –> c, чтобы её параметр передавался между этими функциями. А что если эти две функции – монадические? Что если возвращаемые ими значения были бы монадическими? Если бы у нас была функция типа a –> m b, мы не могли бы просто передать её результат функции типа b –> m c, потому что эта функция принимает обычное значение b, не монадическое. Чтобы всё-таки достичь нашей цели, можно воспользоваться операцией <=<:
(<=<) :: (Monad m) => (b –> m c) –> (a –> m b) –> (a –> m c)
f <=< g = (x –> g x >>= f)
Поэтому теперь мы можем производить композицию двух монадических функций:
ghci> let f x = [x,-x]
ghci> let g x = [x*3,x*2]
ghci> let h = f <=< g
ghci> h 3
[9,-9,6,-6]
Ладно, всё это здорово. Но какое это имеет отношение к закону ассоциативности? Просто, когда мы рассматриваем этот закон как закон композиций, он утверждает, что f <=< (g <=< h) должно быть равнозначно (f <=< g) <=< h. Это всего лишь ещё один способ доказать, что для монад вложенность операций не должна иметь значения.
Если мы преобразуем первые два закона так, чтобы они использовали операцию <=<, то закон левого тождества утверждает, что для каждой монадической функции f выражение f <=< return означает то же самое, что просто вызвать f. Закон правого тождества говорит, что выражение return <=< f также ничем не отличается от простого вызова f. Это подобно тому, как если бы f являлась обычной функцией, и тогда (f . g) . h было бы аналогично f . (g . h), выражение f . id – всегда аналогично f, и выражение id . f тоже ничем не отличалось бы от вызова f.
В этой главе мы в общих чертах ознакомились с монадами и изучили, как работают монада 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:

