>Just "3!"
Это мы уже проходили! Передача монадического значения функции, которая возвращает монадическое значение, – ничего особенного. Заметьте, как параметр >x
становится равным значению >3
внутри анонимной функции, когда мы выполняем код. Как только мы внутри этой анонимной функции, это просто обычное значение, а не монадическое. А что если бы у нас был ещё один вызов оператора >>>=
внутри этой функции? Посмотрите:
>ghci> Just 3 >>= (\x –> Just "!" >>= (\y –> Just (show x ++ y)))
>Just "3!"
Ага-а, вложенное использование операции >>>=
! Во внешней анонимной функции мы передаём значение >Just "!"
анонимной функции >\y –> Just (show x ++ y)
. Внутри этой анонимной функции параметр >y
становится равным >"!"
. Параметр >x
по-прежнему равен >3
, потому что мы получили его из внешней анонимной функции. Всё это как будто напоминает мне о следующем выражении:
>ghci> let x = 3; y = "!" in show x ++ y
>"3!"
Главное отличие состоит в том, что значения в нашем примере с использованием оператора >>>=
являются монадическими. Это значения с контекстом неудачи. Мы можем заменить любое из них на неудачу:
>ghci> Nothing >>= (\x –> Just "!" >>= (\y –> Just (show x ++ y))) Nothing
>ghci> Just 3 >>= (\x –> Nothing >>= (\y –> Just (show x ++ y)))
>Nothing
>ghci> Just 3 >>= (\x –> Just "!" >>= (\y –> Nothing))
>Nothing
В первой строке передача значения >Nothing
функции естественным образом даёт в результате >Nothing
. Во второй строке мы передаём значение >Just 3
функции, и параметр >x
становится равным >3
. Но потом мы передаём значение >Nothing
внутренней анонимной функции, и результатом становится >Nothing
, что заставляет внешнюю анонимную функцию тоже произвести >Nothing
в качестве своего результата. Это что-то вроде присвоения значений переменным в выражениях >let
, только значения, о которых идёт речь, являются монадическими.
Чтобы проиллюстрировать эту идею, давайте запишем следующие строки в сценарий так, чтобы каждое значение типа >Maybe
занимало свою собственную строку:
>foo :: Maybe String
>foo = Just 3 >>= (\x –>
> Just "!">>= (\y –>
> Just (show x ++ y)))
Чтобы уберечь нас от написания всех этих раздражающих анонимных функций, язык Haskell предоставляет нам нотацию >do
. Она позволяет нам записать предыдущий кусок кода вот так:
>foo :: Maybe String
>foo = do
> x <– Just 3
> y <– Just "!"
> Just (show x ++ y)
Могло показаться, что мы получили возможность временно извлекать сущности из значений типа >Maybe
без необходимости проверять на каждом шагу, являются ли значения типа >Maybe
значениями в конструкторе >Just
или значениями