Da "fold" nicht leistungsfähig genug ist, um einen hübschen Baumdrucker mit Einrückung zu schreiben, was ist ein Kombinator höherer Ordnung?
Zum Beispiel den folgenden Baumdatentyp:
data Tree a = Node [Tree a] | Leaf a deriving Show
type Sexp = Tree String
Wie drücke ich eine "hübsche" Funktion mit einem Kombinator höherer Ordnung aus, der den Baum mit der richtigen Einrückung druckt? Beispielsweise
sexp =
Node [
Leaf "aaa",
Leaf "bbb",
Node [
Leaf "ccc",
Leaf "ddd",
Node [
Leaf "eee",
Leaf "fff"],
Leaf "ggg",
Leaf "hhh"],
Leaf "jjj",
Leaf "kkk"]
pretty = ????
main = print $ pretty sexp
Ich möchte, dass das Ergebnis dieses Programms ist:
(aaa
bbb
(ccc
ddd
(eee
fff)
ggg
hhh)
jjj
kkk)
Hier ist eine unvollständige Lösung, die eine "Falte" als Kombinator verwendet und die Einrückung nicht implementiert:
fold f g (Node children) = f (map (fold f g) children)
fold f g (Leaf terminal) = g terminal
pretty = fold (\ x -> "(" ++ (foldr1 ((++) . (++ " ")) x) ++ ")") show
main = putStrLn $ pretty sexp
s ist offensichtlich nicht möglich, die gewünschte Funktion mit @ zu schreibefold
, da es die Baumstruktur vergisst. Also, was ist ein richtiger Kombinator höherer Ordnung, der generisch genug ist, um mir das Schreiben der gewünschten Funktion zu ermöglichen, aber weniger leistungsfähig als das Schreiben einer direkten rekursiven Funktion?