. Вот классно!.. Если какое-либо из значений, которые мы пытаемся извлечь, равно
>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
со всеми предыдущими монадическими значениями, сцепленными с ним.
Инструкция нашего канатоходца может также быть выражена с использованием нотации >do
. Функции >landLeft
и >landRight
принимают количество птиц и шест и производят шест, обёрнутый в >Just
. Исключение – это когда канатоходец соскальзывает, и тогда возвращается значение >Nothing
. Мы использовали операцию >>>=
для сцепления последовательных шагов, потому что каждый из них зависел от предыдущего и каждый обладал добавленным контекстом возможной неудачи. Здесь две птицы приземляются с левой стороны, затем две птицы – с правой, а потом одна птица – снова с левой:
>routine :: Maybe Pole
>routine = do
> start <– return (0, 0)
> first <– landLeft 2 start
> second <– landRight 2 first