>Just 3
>ghci> Just 1 `applyMaybe` \x –> if x > 2 then Just x else Nothing
>Nothing
Результаты оказались такими, каких мы и ждали! Если монадическое значение слева равно >Nothing
, то всё будет равно >Nothing
. А если функция справа возвращает значение >Nothing
, результатом опять будет >Nothing
. Это очень похоже на тот случай, когда мы использовали тип >Maybe
в качестве аппликативного функтора и в результате получали значение >Nothing
, если где-то в составе присутствовало значение >Nothing
.
Похоже, мы догадались, как взять причудливое значение, передать его функции, которая принимает обычное значение, и вернуть причудливое значение. Мы сделали это, помня, что значение типа >Maybe
представляет вычисление, которое могло окончиться неуспешно.
Вы можете спросить себя: «Чем это полезно?» Может показаться, что аппликативные функторы сильнее монад, поскольку аппликативные функторы позволяют нам взять обычную функцию и заставить её работать со значениями, имеющими контекст. В этой главе вы увидите, что монады, будучи усовершенствованными аппликативными функторами, тоже способны на такое. На самом деле они могут делать и кое-какие другие крутые вещи, на которые не способны аппликативные функторы.
Мы вернёмся к >Maybe
через минуту, но сначала давайте взглянем на класс типов, который относится к монадам.
Как и функторы, у которых есть класс типов >Functor
, и аппликативные функторы, у которых есть класс типов >Applicative
, монады обладают своим классом типов: >Monad
! (Ух ты, кто бы мог подумать?)
>class Monad m where
> return :: a –> m a
> (>>=) :: m a –> (a –> m b) –> m b
> (>>) :: m a –> m b –> m b
> x >> y = x >>= \_ –> y
> fail :: String –> m a
> fail msg = error msg
В первой строке говорится >class Monad m where
. Стойте, не говорил ли я, что монады являются просто расширенными аппликативными функторами? Не надлежит ли здесь быть ограничению класса наподобие >class (Applicative m) => Monad m where
, чтобы тип должен был являться аппликативным функтором, прежде чем он может быть сделан монадой? Ладно, положим, надлежит, – но когда появился язык Haskell, людям не пришло в голову, что аппликативные функторы хорошо подходят для этого языка. Тем не менее будьте уверены: каждая монада является аппликативным функтором, даже если в объявлении класса >Monad
этого не говорится.
Первой функцией, которая объявлена в классе типов >Monad
, является >return
. Она аналогична функции >pure
, находящейся в классе типов >Applicative
. Так что, хоть она и называется по-другому, вы уже фактически с ней знакомы. Функция