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?

Respuestas a la pregunta(2)

Su respuesta a la pregunta