Аппликативный функтор Maybe
Давайте взглянем на реализацию экземпляра класса >Applicative
для типа >Maybe
:
>instance Applicative Maybe where
> pure = Just
> Nothing <*> _ = Nothing
> (Just f) <*> something = fmap f something
Опять же из определения класса мы видим, что идентификатор >f
, который играет роль аппликативного функтора, должен принимать один конкретный тип в качестве параметра. Поэтому мы пишем >instance Applicative Maybe where
вместо >instance Applicative (Maybe a) where
.
Далее, у нас есть функция >pure
. Вспомните, что функция должна что-то принять и обернуть в аппликативное значение. Мы написали >pure = Just
, потому что конструкторы данных вроде >Just
являются обычными функциями. Также можно было бы написать >pure x = Just x
.
Наконец, у нас есть определение оператора ><*>
. Извлечь функцию из значения >Nothing
нельзя, поскольку внутри него нет функции. Поэтому мы говорим, что если мы пробуем извлечь функцию из значения >Nothing
, результатом будет то же самое значение >Nothing
.
В определении класса >Applicative
есть ограничение класса >Functor
– значит, мы можем считать, что оба параметра оператора ><*>
являются значениями функтора. Если первым аргументом выступает не значение >Nothing
, а >Just
с некоторой функцией внутри, то мы говорим, что с помощью данной функции хотим отобразить второй параметр. Этот код также заботится о случае, когда вторым аргументом является значение >Nothing
, потому что его отображение с помощью любой функции при использовании метода >fmap
вернёт всё то же >Nothing
. Итак, в случае с типом >Maybe
оператор ><*>
извлекает функцию из значения слева, если это >Just
, и отображает с её помощью значение справа. Если какой-либо из параметров является значением >Nothing
, то и результатом будет >Nothing
.
Теперь давайте это опробуем:
>ghci> Just (+3) <*> Just 9
>Just 12
>ghci> pure (+3) <*> Just 10
>Just 13
>ghci> pure (+3) <*> Just 9
>Just 12
>ghci> Just (++"ха-ха") <*> Nothing Nothing
>ghci> Nothing <*> Just "во-от"
>Nothing
Вы видите, что выполнение выражений >pure (+3)
и >Just (+3)
в данном случае – одно и то же. Используйте функцию >pure
, если имеете дело со значениями типа >Maybe
в аппликативном контексте (если вы используете их с оператором ><*>
); в противном случае предпочитайте конструктор >Just
.
Первые четыре введённых строки демонстрируют, как функция извлекается, а затем используется для отображения; но в данном случае этого можно было добиться, просто применив не обёрнутые функции к функторам. Последняя строка любопытна тем, что мы пытаемся извлечь функцию из значения >Nothing
, а затем отображаем с её помощью нечто, что в результате даёт