Ein Teil des Problems ist, dass Sie einfach keine Möglichkeit haben, einen leeren Baum darzustellen.
-- Get rid of unnecessary tuple
data Tree a = Empty
| Leaf a
| T (Tree a) (Tree a) deriving (Show, Eq, Ord)
-- A filtered empty tree is still empty
filterT p Empty = Empty
-- A leaf either stays the same or becomes empty
filterT p (Leaf x) | p x = Leaf x
| otherwise = Empty
-- Any other tree is just the result of filtering each child
filterT p (T left right) = T (filterT p left) (filterT p right)
Dies ist keine große Lösung; Es bleibt Ihnen immer noch mit mehreren Möglichkeiten, im Wesentlichen den gleichen Baum zu repräsentieren, da Empty
und T Empty Empty
nicht signifikant unterschiedlich sind. Sie könnten schreiben eine andere Funktion, die solche Bäume "Pflaumen".
prune :: Tree a -> Tree a
prune (T Empty Empty) = Empty
prune x = x
, die in Ihre filterT
Funktion eingebaut werden kann, etwa so:
filterT _ Empty = Empty
filterT p (Leaf x) | p x = Leaf x
| otherwise = Empty
filterT p (T left right) = let prune (T Empty Empty) = Empty
prune x = x
in prune $ T (filterT p left) (filterT p right)
Sie auch prune
verlängern könnte der gleiche Baum einflügelige Bäume auf ein einzelnes Blatt (sollte Tree (Leaf 3) Empty
und Leaf 3
betrachten zu kontrahieren ?), wie in
filterT' _ Empty = Empty
filterT' p (Leaf x) | p x = Leaf x
| otherwise = Empty
filterT' p (T left right) = let prune (T Empty Empty) = Empty
prune (T (Leaf x) Empty)) = Leaf x
prune (T Empty (Leaf x)) = Leaf x
prune x = x
in prune $ T (filterT p left) (filterT p right)
schließlich, ob Sie verwenden prune
wird depe nd ob der gefilterte Baum die Struktur des Originals erhalten soll; Vielleicht möchten Sie beispielsweise zwischen einem Blatt und einem Knoten unterscheiden, der früher zwei Kinder hatte.
Vielen Dank –