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

. Вот классно!.. Если какое-либо из значений, которые мы пытаемся извлечь, равно >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