In der Tat können Sie dem Baum einen Typparameter geben, wie in Alexander Poluektov Beispiel. Einfach genug! Aber warum dort aufhören? Wir können ein bisschen mehr Spaß haben als nur das. Anstatt nur eine rekursive Struktur mit polymorphen Daten, können Sie die Struktur polymorph in der Rekursion selbst machen!
Zuerst die Referenzen des Baums auf sich selbst abstrahieren, in der gleichen Weise wie die Referenzen auf Int
abstrahieren, die rekursiven Referenzen durch einen neuen Parameter t
ersetzen. Das lässt uns mit dieser eher vage Datenstruktur:
data TNode t a = Empty
| Leaf a
| Node (t a) a (t a)
deriving (Eq, Ord, Show, Read)
Dies wurde als TNode
hier umbenannt worden, weil es nicht wirklich ein Baum ist mehr; nur ein einfacher Datentyp. Nun, die ursprüngliche Rekursion zu erholen und einen Baum erstellen, drehen wir TNode
um und ihn an sich selbst:
newtype Tree a = Tree (TNode Tree a) deriving (Eq, Ord, Show, Read)
Jetzt können wir diese Tree
rekursiv verwenden, aber leider auf Kosten von einigen zusätzlichen Wortschwall, etwa so:
Tree (Node (Tree Empty) 5 (Tree (Leaf 2)))
Also, was gibt uns das, neben der zusätzlichen Typisierung, fragen Sie? Einfach, dass wir den Grundbaum Struktur von den Daten, die er enthält, und der Methode, mit der die Daten konstruiert und verarbeitet werden, getrennt haben, was es uns erlaubt, allgemeinere Funktionen zu schreiben, um mit dem einen oder anderen Aspekt umzugehen.
Zum Beispiel können wir Bäume mit zusätzlichen Daten schmücken oder zusätzliche Teile in den Baum einfügen, ohne die generischen Baumfunktionen zu beeinträchtigen.Sagen wir einen Namen zu jedem Stück des Baumes geben wollten:
toList f t = toList' f (f t) []
where toList' f (Node t1 x t2) xs = toList' f (f t1) (x : toList' f (f t2) xs)
toList' f (Leaf x) xs = x:xs
toList' _ Empty xs = xs
Bei einer Funktion der aktuellen TNode
zu extrahieren aus:
newtype NameTree a = NameTree (String, TNode NameTree a) deriving (Eq, Ord, Show, Read)
Auf der anderen Seite können wir allgemeine Baum-Traversal-Logik schreiben eine rekursive Baum, können wir dies auf eine solche Struktur verwenden:
treeToList = toList (\(Tree t) -> t)
nameTreeToList = toList (\(NameTree (_, t)) -> t)
natürlich, das geht wahrscheinlich weit jenseits dessen, was Sie zu tun suchen, aber es ist ein schöner Geschmack davon, wie viel Polymorphismus und generischer Code Haskell erlaubt (nein, ermutigt) einen Programmierer zu erstellen.