Редактировать: Я обычно экспериментирую в ghci, чтобы понять новый код, поэтому для таких, как я, я создал School of Haskell post/page, который поставляется с приведенными ниже примерами, но они доступны для редактирования и запуска.
Подумайте, эти примеры ответят на ваши вопросы, но для целесообразности я собираюсь изменить другой узел. Мои знания о функциях застежки-молнии в lens довольно мелкие. Потребуется немного больше времени, чтобы читать и привыкать к типам в пакете lens по сравнению со многими другими пакетами, но потом это неплохо. Перед этим сообщением я не использовал модуль молнии или модуль дерева в пакете объектива.
Деревья не очень хорошо сочетаются с show
, поэтому, если у меня есть время, я вернусь и добавлю довольно красивую печать, иначе это, вероятно, ключ к работе в реплике с этими примерами, чтобы увидеть, что происходит.
Просмотр
Если я хочу, чтобы просмотреть значение первого узла, в соответствии с tree lens package этом упоминается как корень, то вы можете:
zipperTree & downward root & view focus
Изменение
Для изменить это значение и воссоздать дерево (rezip the tree):
zipperTree & downward root & focus .~ 10 & rezip
Если вы хотите спуститься по веткам, вам необходимо использовать downward branches
. Вот пример, который изменяет корень первой ветви и rezipx дерева:
zipperTree & downward branches
& fromWithin traverse
& downward root
& focus .~ 5
& rezip
Здесь я двигаться вниз к списку Филиалы. Затем я использую fromWithin
использовать traverse
, чтобы пересечь список, если бы это был кортеж, я мог бы использовать both
.
Сохранение и воспроизведение пути обхода
saveTape
и restoreTape
позволяет вам сохранить вашу позицию в молнии, так что он может быть восстановлен последним.
Сохранить позицию:
tape = zipperTree & downward branches
& fromWithin traverse
& downward root
& saveTape
Затем воссоздать обход через дерево я могу:
t <- (restoreTape tape testTree)
Затем вы можете использовать т в качестве новой молнии и изменить его, как обычно:
t & focus .~ 15 & rezip
Лента повторяет шаги, которые вы предприняли, поэтому может работать на других деревьях, поэтому последующие будут работать с t он лента, как определено выше:
testTree2 = Node 1 [ Node 2 [] ]
t2 <- (restoreTape tape testTree2)
t2 & focus .~ 25 & rezip
Изменение нескольких мест
Если вы хотите изменить кратные корни просто держать на reziping молнию. Ниже модифицирует два корня testTree2:
zipper testTree2 & downward root
& focus .~ 11
& upward
& downward branches
& fromWithin traverse
& downward root
& focus .~ 111
& rezip
Благодарим за это. Тем не менее, это не совсем касается моей домашней работы (просто шучу). Я не пытаюсь модифицировать определенный узел. Вместо этого я хочу пересечь все дерево и записать путь к определенному узлу, который удовлетворяет некоторому условию. В вашем «модифицирующем» примере вы знаете, что путь «zipperTree & inside» (root.traverse.branches) >> = saveTape'. Мне было интересно, как я могу получить путь, не зная об этом, прежде чем руки (пройдя его). – Kai
Конкретный пример с более подробной информацией будет полезен тогда. С помощью примитивов выше и рекурсии можно посетить каждый узел в дереве, посмотреть на каждое значение и применить к нему тест. После успешного теста вы просто вернете ленту или сохраните ее в монаде штата или писателя, если это лучше для вашего приложения. – Davorak
Это очень полезно! Как использовать Data.Tree.Lens для собственных типов деревьев? В частности, что, если его двоичное дерево вместо розового дерева? – nont