Sie möchten die gesamte Datenstruktur durchlaufen und einige Elemente hier und da ändern. Dies geschieht in der Regel durch eine Funktion, die die Datenstruktur als Parameter nimmt und die neue, geänderte Version der Struktur zurückgibt.
Für jeden Fall der Eingabe definiert diese Funktion, wie der neue Wert, der zurückgegeben wird, aussehen soll aussehen soll.
Die Grundfunktion, die eine Tree
(das ist nur eine Liste von DataA
Werte) sollte wahrscheinlich einfach eine neue Liste mit geänderten Werten zurückgeben. Wenn wir diese Änderungen an den Werten auf eine modifyA
Funktion, die wichtigste Änderung Funktion sieht wie folgt aus:
-- # 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)
Jetzt ist die mutateA
Funktion muss definiert werden, um alle möglichen DataA
Werte, und am besten begleitet von einem mutateB
Funktion, die die DataB
Werte.
Diese Funktionen untersuchen die verschiedenen möglichen Fälle von Werten und geben die entsprechenden neuen Werte zurück:
-- # 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"
Auf diese Weise wird für jedes Element im Baum ein neues Element berechnet, wobei alle DataB2
Werte an beliebiger Stelle im Baum werden durch "foo" ersetzt.
Es ist relativ ausführlich, weil Sie fünf verschiedene Fälle haben, die eine Liste enthalten von Werten enthält, die durchlaufen werden muss, aber das ist nicht spezifisch für Haskell. In einer imperativen Sprache würde man normalerweise fünf for-Schleifen anstelle der fünf Aufrufe an map
.
Vielleicht könnten Sie Ihre Datenstruktur vereinfachen, um diesen "Overhead" zu verringern. Diese hängt natürlich von Ihrem tatsächlichen Anwendungsfall ab, aber vielleicht brauchen Sie zum Beispiel nicht die Data2
Fälle: Gibt es einen Unterschied zwischen DataA2 "abc"
y DataA3 "abc" []
?