Ага-а, вложенное использование операции >>=
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
или значениями Nothing
. Вот классно!.. Если какое-либо из значений, которые мы пытаемся извлечь, равно Nothing
, всё выражение do
в результате вернёт значение Nothing
. Мы выдёргиваем наружу их значения (если таковые существуют) и перекладываем необходимость беспокойства о контексте, идущем с этими значениями, на плечи оператора >>=
.Выражения do
Делай как я
В выражении do
let
, является монадическим значением. Чтобы просмотреть её результат, мы используем символ <–
. Если у нас есть значение типа Maybe String
и мы привязываем её к образцу с помощью символа <–
, этот образец будет иметь тип String
так же, как когда мы использовали операцию >>=
для передачи монадических значений анонимным функциям.Последнее монадическое значение в выражении do
Just (show x ++ y)
в этом примере – не может быть использовано с символом <–
для привязки его результата, потому что если бы мы преобразовали выражение do
обратно в цепочку применений оператора >>=
, это не имело бы смысла. Наоборот, результат последнего выражения является результатом всего склеенного монадического значения, учитывая возможную неудачу вычисления каждого из предыдущих монадических значений. Рассмотрите, например, следующую строку:ghci> Just 9 >>= (\x –> Just (x > 8))
Just True
Поскольку левым параметром функции >>=
Just
, анонимная функция применяется к значению 9
, и результатом становится значение Just True
. Мы можем переписать это в нотации do
следующим образом:marySue :: Maybe Bool
marySue = do
x <– Just 9
Just (x > 8)
Сравнивая оба варианта, легко увидеть, почему результатом всего монадического значения является результат последнего монадического значения в выражении do
Пьер возвращается