с типом
>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
. Вот она в исходном коде:
>applyMaybe :: Maybe a –> (a –> Maybe b) –> Maybe b
>applyMaybe Nothing f = Nothing
>applyMaybe (Just x) f = f x
Теперь давайте с ней поиграем. Мы будем использовать её как инфиксную функцию так, чтобы значение типа >Maybe
было слева, а функция была справа:
>ghci> Just 3 `applyMaybe` \x –> Just (x+1)
>Just 4
>ghci> Just "смайлик" `applyMaybe` \x –> Just (x ++ " :)")
>Just "смайлик :)"
>ghci> Nothing `applyMaybe` \x –> Just (x+1)
>Nothing
>ghci> Nothing `applyMaybe` \x –> Just (x ++ " :)")
>Nothing
В данном примере, когда мы использовали функцию >applyMaybe
со значением >Just
и функцией, функция просто применялась к значению внутри конструктора >Just
. Когда мы попытались использовать её со значением >Nothing
, весь результат был равен >Nothing
. Что насчёт того, если функция возвращает >Nothing
? Давайте посмотрим:
>ghci>Just 3 `applyMaybe` \x –> if x > 2 then Just x else Nothing