The following code creates a simple tree structure and then walks through the tree looking for node with the value 9 that appears after we have seen a node with the value 1 and a node with the value 4 (order of the 1 and 4 don't matter).
type N = Value of int | Children of N list
type S = {oneFound:bool; fourFound:bool}
let walk () =
let mutable state = {oneFound = false; fourFound = false}
let rec walkImpl curNode =
match curNode with
| Value n -> match n with
| 1 -> state <- {state with oneFound = true }
| 4 -> state <- {state with fourFound = true }
| 9 -> if state.oneFound && state.fourFound then
printfn "Found a good 9"
else
printfn "Found a bad 9"
| _ -> ()
printfn "Node value %d" n
| Children c -> c |> List.iter (fun n -> walkImpl n)
walkImpl (Children [Value 1; Value 2 ; Children [Value 9; Children [Value 4; Value 5]; Value 9]])
walk ()
When I run it produces the correct output:
Node value 1
Node value 2
Found a bad 9
Node value 9
Node value 4
Node value 5
Found a good 9
Node value 9
Is there a method to do this that threads the state through the recursive function calls rather than making it a mutable variable? The mutability is confined to my function but I keep thinking there must be a way to structure this that makes it unnecessary.
In real life the tree structure will be much larger, several thousand nodes and 10 levels deep, while the code has not run into any recursion limits yet are there improvements that would make this less likely?