и обернуть его так, чтобы оно превратилось в
>Just 1
. Или можем превратить его в
>[1]
. Оно могло бы даже стать действием ввода-вывода, которое ничего не делает, а просто выдаёт
>1
. Функция, которая за это отвечает, называется
>pure
.
Аппликативное значение можно рассматривать как значение с добавленным контекстом – «причудливое» значение, выражаясь техническим языком. Например, буква >'a'
– это просто обычная буква, тогда как значение >Just 'a'
обладает неким добавленным контекстом. Вместо типа >Char
у нас есть тип >Maybe Char
, который сообщает нам, что его значением может быть буква; но значением может также быть и отсутствие буквы. Класс типов >Applicative
позволяет нам использовать с этими значениями, имеющими контекст, обычные функции, и этот контекст сохраняется. Взгляните на пример:
>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
, передать значение функции легче лёгкого: мы применяем функцию к значению как обычно – вот и всё! Но когда мы имеем дело со значениями, находящимися в определённом контексте, нужно немного поразмыслить, чтобы понять, как эти причудливые значения передаются функциям и как учесть их поведение. Впрочем, вы сами убедитесь, что это так же просто, как раз, два, три.