Учитывая, например, следующий тип данных дерева:
data Tree a = Node [Tree a] | Leaf a deriving Show
type Sexp = Tree String
Как выразить "симпатичную" функцию с помощью комбинатора высокого порядка, который печатает дерево с соответствующим отступом? Например:
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
Я хочу, чтобы результатом этой программы было:
(aaa
bbb
(ccc
ddd
(eee
fff)
ggg
hhh)
jjj
kkk)
Вот неполное решение, используя "сгиб" в качестве комбинатора, который не выполняет отступ:
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
Очевидно, что невозможно записать функцию, которую я хочу использовать fold
, поскольку она забывает древовидную структуру. Итак, что такое правильный комбинатор высокого порядка, который достаточно общий, чтобы позволить мне написать функцию, которую я хочу, но менее мощный, чем запись прямой рекурсивной функции?