Вы хотите просмотреть всю структуру данных и изменить некоторые элементы здесь и там.
Обычно это делается функцией, которая принимает структуру данных в качестве параметра и
возвращает новую, измененную версию структуры.
Для каждого случая ввода эта функция определяет, как должно возвращаться новое значение
похож.
Основная функция, которая изменяет Tree
(это просто список DataA
значений)
вероятно, следует просто вернуть новый список измененных значений. Если мы отложим эти
модификация значений для функции modifyA
, основная модификация
функция выглядит так:
-- # function to change a |Tree|
mutate :: Tree -> Tree
mutate as = map mutateA as
-- # (The |map| function applies the |mutateA| function to every
-- # element of |as|, creating a list of all the return values)
Теперь необходимо определить функцию mutateA
, чтобы изменить все возможные значения DataA
, и
лучше всего это сопровождается функцией mutateB
, которая обрабатывает значения DataB
.
Эти функции смотрят на различные возможные случаи значений и возвращают
соответствующие новые значения:
-- # function to change |DataA| items
mutateA :: DataA -> DataA
-- # A |DataA1| is a |DataA1| with modified values
mutateA (DataA1 bs) = DataA1 (map mutateB bs)
-- # A |DataA3| is a |DataA3| with modified values
mutateA (DataA3 s as) = DataA3 s (map mutateA as)
-- # In the remaining case(s) the value stays the same
mutateA d = d
-- # function to change |DataB| items
mutateB :: DataB -> DataB
mutateB (DataB1 as) = DataB1 (map mutateA as)
mutateB (DataB3 s bs) = DataB3 s (map mutateB bs)
-- # Here comes a real change
mutateB (DataB2 _) = DataB2 "foo"
Таким образом, для каждого элемента в дереве вычисляется новый элемент, где все DataB2
значения в любом месте дерева заменяются на «foo».
Это довольно многословно, потому что у вас есть пять разных случаев, которые содержат список
значений, которые нужно пройти, но это не характерно для Haskell. В
императивный язык, вы бы обычно имели пять петель вместо пяти
звонки на map
.
Возможно, вы могли бы упростить структуру данных, чтобы уменьшить эти «накладные расходы». это
конечно, зависит от вашего фактического варианта использования, но, может быть, например, вам не нужно
случаи Data2
:
Есть ли разница между DataA2 "abc"
и DataA3 "abc" []
?