>ghci> let newFocus = farLeft –: attach (Node 'Z' Empty Empty)
Значение >newFocus
теперь сфокусировано на дереве, которое мы только что прикрепили, а остальная часть дерева находится в «хлебных крошках» в вывернутом наизнанку виде. Если бы мы использовали функцию >goUp
для прохода всего пути к вершине дерева, оно было бы таким же деревом, как и >freeTree
, но с дополнительным символом >'Z'
на дальнем левом краю.
Идём прямо на вершину, где воздух чист и свеж!
Создать функцию, которая проходит весь путь к вершине дерева, независимо от того, на чём мы фокусируемся, очень просто. Вот она:
>topMost :: Zipper a –> Zipper a
>topMost (t, []) = (t, [])
>topMost z = topMost (goUp z)
Если наша расширенная тропинка из «хлебных крошек» пуста, это значит, что мы уже находимся в корне нашего дерева, поэтому мы просто возвращаем текущий фокус. В противном случае двигаемся вверх, чтобы получить фокус родительского узла, а затем рекурсивно применяем к нему функцию >topMost
.
Итак, теперь мы можем гулять по нашему дереву, двигаясь влево, вправо и вверх, применяя функции >modify
и >attach
во время нашего путешествия. Затем, когда мы покончили с нашими изменениями, используем функцию >topMost
, чтобы сфокусироваться на вершине дерева и увидеть произведённые нами изменения в правильной перспективе.
Застёжки могут использоваться почти с любой структурой данных, поэтому неудивительно, что они работают с подсписками списков. В конце концов, списки очень похожи на деревья, только узел дерева содержит (или не содержит) элемент и несколько поддеревьев, а узел списка – элемент и лишь один подсписок. Когда мы реализовывали свои собственные списки в главе 7, то определили наш тип данных вот так:
>data List a = Empty | Cons a (List a) deriving (Show, Read, Eq, Ord)
Сравните это с определением нашего бинарного дерева – и легко увидите, что списки можно воспринимать в качестве деревьев, где каждый узел содержит лишь одно поддерево.
Список вроде >[1,2,3]
может быть записан как >1:2:3:[]
. Он состоит из «головы» списка равной >1
и «хвоста», который равен >2:3:[]. 2:3:[]
также имеет «голову», которая равна >2
, и «хвост», который равен >3:[]
. Для >3:[]
«голова» равна >3
, а «хвост» является пустым списком >[]
.
Давайте создадим застёжку для списков. Чтобы изменить фокус на подсписках списка, мы перемещаемся или вперёд, или назад (тогда как при использовании деревьев мы перемещались вверх, влево или вправо). Помещённой в фокус частью будет подсписок, а кроме того, мы будем оставлять «хлебные крошки» по мере нашего движения вперёд.