I am fascinated by the approach used in this blog post to traverse a rose tree a.k.a multiway tree a.k.a n-ary tree using CPS.
Here is my code, with type annotations removed and names changed, which I did while trying to understand the technique:
type 'a Tree = Node of 'a * 'a Tree list | Leaf of 'a
let rec reduce recCalls cont =
match recCalls with
| [] -> [] |> cont
| findMaxCall :: pendingCalls ->
findMaxCall (fun maxAtNode ->
reduce pendingCalls (fun maxVals -> maxAtNode :: maxVals |> cont))
let findMaxOf (roseTree : int Tree) =
let rec findMax tr cont =
match tr with
| Leaf i -> i |> cont
| Node (i, chld) ->
let recCalls = chld |> List.map findMax
reduce recCalls (fun maxVals -> List.max (i :: maxVals) |> cont)
findMax roseTree id
// test it
let FindMaxOfRoseTree =
let t = Node (1, [ Leaf 2; Leaf 3 ])
let maxOf = findMaxOf t //will be 3
maxOf
My problem is, I find this approach hard to follow. The mutual recursion (assuming that's the right term) is really clever to my simpleton brain, but I get lost while trying to understand how it works, even when using simple examples and writing down steps manually etc.
I am in need of using CPS with Rose trees, and I'll be doing the kind of traversals that require a CPS, because just like this example, computing results based on my my tree nodes require that children of the nodes are computed first. In any case, I do like CPS and I'd like to improve my understanding of it.
So my question is: Is there an alternative way of implementing CPS on rose trees which I may manage to better follow understand? Is there a way to refactor the above code which may make it easier to follow (eliminating the mutual recursion?)
If there is a name for the above approach, or some resources/books I can read to understand it better, hints are also most welcome.