Изучай Haskell во имя добра! (Липовача) - страница 228

>Nothing

Как бы это выглядело, если бы мы не сделали разумный выбор, обработав значения типа >Maybe как значения с контекстом неудачи и передав их функциям? Вот какой была бы последовательность приземлений птиц:

>routine :: Maybe Pole

>routine = case landLeft 1 (0, 0) of

>   Nothing –> Nothing

>   Just pole1 –> case landRight 4 pole1 of

>      Nothing –> Nothing

>      Just pole2 –> case landLeft 2 pole2 of

>         Nothing –> Nothing

>         Just pole3 –> landLeft 1 pole3



Мы усаживаем птицу слева, а затем проверяем вероятность неудачи и вероятность успеха. В случае неудачи мы возвращаем значение >Nothing. В случае успеха усаживаем птиц справа, а затем повторяем всё сызнова. Превращение этого убожества в симпатичную цепочку монадических применений с использованием функции >>>= является классическим примером того, как монада >Maybe экономит массу времени, когда вам необходимо последовательно выполнить вычисления, основанные на вычислениях, которые могли окончиться неуспешно.

Обратите внимание, каким образом реализация операции >>>= для типа >Maybe отражает именно эту логику, когда проверяется, равно ли значение >Nothing, и действие производится на основе этих сведений. Если значение равно >Nothing, она незамедлительно возвращает результат >Nothing. Если значение не равно >Nothing, она продолжает работу с тем, что находится внутри конструктора >Just.

В этом разделе мы рассмотрели, как некоторые функции работают лучше, когда возвращаемые ими значения поддерживают неудачу. Превращая эти значения в значения типа >Maybe и заменяя обычное применение функций вызовом операции >>>=, мы практически даром получили механизм обработки вычислений, которые могут оканчиваться неудачно. Причина в том, что операция >>>= должна сохранять контекст значения, к которому она применяет функции. В данном случае контекстом являлось то, что наши значения были значениями с неуспехом в вычислениях. Поэтому когда мы применяли к таким значениям функции, всегда учитывалась вероятность неуспеха.

Нотация do

Монады в языке Haskell настолько полезны, что они обзавелись своим собственным синтаксисом, который называется «нотация do». Вы уже познакомились с нотацией >do в главе 8, когда мы использовали её для объединения нескольких действий ввода-вывода. Как оказывается, нотация >do предназначена не только для системы ввода-вывода, но может использоваться для любой монады. Её принцип остаётся прежним: последовательное «склеивание» монадических значений.

Рассмотрим этот знакомый пример монадического применения:

>ghci> Just 3 >>= (\x –> Just (show x ++ "!"))