Rufflewind's answer is the most obvious way to correct a dubious foldtree definition from Hughes' famous article. However, there is a much more concise and modular solution that requires only one line of code and reuse of foldr . Scroll to the end of this message to see this definition. Read on for some definition definition.
Compare the definition of Rufflewind foldforest :
foldforest fga (Cons subtree rest) = g (foldtree fga subtree) (foldforest fga rest) foldforest fga Nil = a
... with Hughes (slightly modified) definition of foldr from the article:
foldr fa (Cons e rest) = fe (foldr fa rest) foldr fa Nil = a
Do they both look terribly similar? In fact, the only difference is that in foldforest we apply foldtree fga to subtree and (through recursion) to all the other elements in the list of subtrees before we "merge" them with g . Is it possible to define an operator that does this and can be passed to foldr ?
foldforest out the foldforest kernel, where the actual work is done: g (foldtree fga subtree) . Using the functional composition (defined in the work of Hughes as (f . g) h = f (gh) ), we can express this part in different ways:
foldforest fga (Cons subtree rest) = (g . foldtree fga) subtree (foldforest fga rest)
Now let's define h = (g . foldtree fga) for brevity and pass the specific list of subtrees to foldforest , foldforest the recursion using our new notation:
foldforest fga (Cons subtree1 (Cons subtree2 Nil)) = h subtree1 (h subtree2 a)
What does a recursion deployment of a similar call to foldr look like?
foldr fa (Cons subtree1 (Cons subtree2 Nil)) = f subtree1 (f subtree2 a)
Now itโs obvious that we managed to extract the operator from foldforest , which we can pass to foldr along with the start state a and the list Treeof s. A complete foldtree definition that maximizes modularity and conciseness should be:
foldtree fga (Node label subtrees) = f label (foldr (g . foldtree fga) a subtrees)
Good night nerd pride
source share