Dado que "doblar" no es lo suficientemente potente como para escribir una bonita impresora de árbol con sangría, ¿qué combinador de alto orden es?
Dado, por ejemplo, el siguiente tipo de datos de árbol:
data Tree a = Node [Tree a] | Leaf a deriving Show
type Sexp = Tree String
¿Cómo expreso una función "bonita" usando un combinador de alto orden, que imprime el árbol con la sangría adecuada? Por ejemplo:
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
Quiero que el resultado de ese programa sea:
(aaa
bbb
(ccc
ddd
(eee
fff)
ggg
hhh)
jjj
kkk)
Aquí hay una solución incompleta, usando un "pliegue" como combinador, que no implementa la sangría:
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
Obviamente no es posible escribir la función que quiero usarfold
, ya que olvida la estructura de árbol. Entonces, ¿qué es un combinador de alto orden adecuado que sea lo suficientemente genérico como para permitirme escribir la función que quiero, pero menos potente que escribir una función recursiva directa?