Миран Липовача - Изучай Haskell во имя добра!
ghci> let coolTree = Node 1 Empty (Node 3 Empty Empty)
ghci> return (coolTree, []) >>= goRight
Just (Node 3 Empty Empty,[RightCrumb 1 Empty])
ghci> return (coolTree, []) >>= goRight >>= goRight
Just (Empty,[RightCrumb 3 Empty,RightCrumb 1 Empty])
ghci> return (coolTree, []) >>= goRight >>= goRight >>= goRight
Nothing
Мы использовали функцию return, чтобы поместить застёжку в конструктор Just, а затем прибегли к оператору >>=, чтобы передать это дело нашей функции goRight. Сначала мы создали дерево, которое в своей левой части имеет пустое поддерево, а в правой – узел, имеющий два пустых поддерева. Когда мы пытаемся пойти вправо один раз, результатом становится успех, потому что операция имеет смысл. Пойти вправо во второй раз – тоже нормально. В итоге мы получаем фокус на пустом поддереве. Но идти вправо третий раз не имеет смысла: мы не можем пойти вправо от пустого поддерева! Поэтому результат – Nothing.
Теперь мы снабдили наши деревья «сеткой безопасности», которая поймает нас, если мы свалимся. (Ух ты, хорошую метафору я подобрал.)
ПРИМЕЧАНИЕ. В нашей файловой системе также имеется много случаев, когда операция может завершиться неуспешно, как, например, попытка сфокусироваться на несуществующем файле или каталоге. В качестве упражнения вы можете снабдить нашу файловую систему функциями, которые завершаются неудачей мягко, используя монаду Maybe.
Благодарю за то, что прочитали!
…Или, по крайней мере, пролистали до последней страницы! Я надеюсь, вы нашли эту книгу полезной и весёлой. Я постарался дать вам хорошее понимание языка Haskell и его идиом. Хотя при изучении этого языка всегда открывается что-то новое, вы теперь сможете писать классный код, а также читать и понимать код других людей. Так что скорее приступайте к делу! Увидимся в мире программирования!
Примечания
1
В современных версиях интерпретатора GHCi для печати результатов вычислений используется функция show, которая представляет кириллические символы соответствующими числовыми кодами Unicode. Поэтому в следующем листинге вместо строки "лама" будет фактически выведено "1083107210841072". В тексте книги для большей понятности кириллица в результатах оставлена без изменений. – Прим. ред.
2
На самом деле любую функцию, число параметров которой больше одного, можно записать в инфиксной форме, заключив её имя в обратные апострофы и поместив её в таком виде ровно между первым и вторым аргументом. – Прим. ред.
3
На самом деле в определении функций они называются образцами, но об этом пойдёт речь далее. – Прим. ред.
4
Вообще говоря, конструкцию с if можно определить в виде функции:
if' :: Bool –> a –> a –> a
if' True x _ = x
if' False _ y = y
Конструкция введена в язык Haskell на уровне ключевого слова для того, чтобы минимизировать количество скобок в условных выражениях. – Прим. ред.
5
Следует отметить, что операторами называются двухместные инфиксные функции, имена которых состоят из служебных символов: +, *, >>= и т. д. – Прим. ред.
6
Однако есть нульместный кортеж, обозначаемый в языке Haskell как (). – Прим. ред.
7
На деле в образцах нельзя использовать операторы, представляющие собой двухместные функции (например, +, / и ++), поскольку при сопоставлении с образцами производится, по сути, обратная операция. Как сопоставить заданное число 5 с образцом (x + y)? Это можно сделать несколькими способами, то есть ситуация неопределённа. Между тем оператор : является конструктором данных (все бинарные операторы, начинающиеся с символа :, могут использоваться как конструкторы данных), поэтому для него можно произвести однозначное сопоставление. — Прим. ред.
8
Это так. В качестве упражнения повышенной сложности читателю рекомендуется реализовать при помощи свёртки функции drop и dropWhile из стандартной библиотеки. – Прим. ред.
9
В тех же целях издательством «ДМК Пресс» выпущена книга: Душкин Р. В. Справочник по языку Haskell. – М.: ДМК Пресс, 2008. – 544 стр., ил. ISBN 5–94074–410–9.
10
На самом деле в синтаксисе языка Haskell имеются ещё так называемые (n + k)-образцы. Впрочем, большая часть сообщества языка их отвергает. – Прим. ред.
11
Текст этого раздела переработан в соответствии с современным стилем обработки исключений. – Прим. ред.
12
Читателей, знакомых с комбинаторной логикой, такое определение экземпляра класса Applicative для функционального типа смутить не должно – методы определяют комбинаторы K и S соответственно. – Прим. ред.
13
Специалисты по нечёткой логике могут увидеть в этом определении троичную логику Лукасевича. – Прим. ред.
14
Это определение представляет собой один из возможных способов обхода двоичного дерева: «левый – корень – правый». Читатель может самостоятельно реализовать экземпляры для представления других способов обхода двоичных деревьев. – Прим. ред.
15
Если версия пакетов языка Haskell base и mtl, установленных в вашей системе, выше соответственно 4.3.1.0 и 2.0.1.0, вам нужно импортировать модуль Control.Monad.Error в ваш скрипт или Control.Monad.Instances в интерпретатор GHCi, перед тем как вы сможете использовать функции экземпляра класса Monad для типа Either. Это связано с тем, что в этих версиях пакетов объявления экземпляров были перенесены в модуль Control.Monad.Instances. – Прим. перев.