I am trying to write a function in which records all paths that lead to data N.
can anyone give me some pointers as im getting confused, when do i record the path? as if i start at the beginning i may end up with paths that lead to know where. (Recording paths as L | R)
Can anyone give me some logic on this!
Thanks
I have worked on trees with a given path, but this i cant figure out
data Tree = N | F Tree Tree deriving Show
data Dir = L | R deriving Show
type Path = [Dir]
so a tree could be F N (F (F N N) (F N (F N N)))
and a path would be [L,L,L,R]
I have made functions to insert where there are N nodes or at a given path.
But i cant get my head round the logic of recording the paths.
Result
I use the list monad to pick both L and R “simultaneously”, and descend both branches. Gotta love nondeterminism!
Explanation:
I hope
descendis clear enough. You give it a tree and a direction, and it descends the tree in that direction.findAllLeavesis the interesting one. How does it work?We’ll talk about the base case,
findAllLeaves N = [[]], in a minute.The recursive case is written in the list monad, with
donotation. The first line is simple: chooseLorRand assign this todir. The list monad will actually choose both, and take the results for each and concatenate them together. This is they key thing to understand. It’s exactly what you asked for: What are all the paths starting withL, and what are all the paths starting withR? Put those together and you have all the paths from the current node to its descendant leaf nodes.The second line should be fairly clear from the previous paragraph’s description. Descend the tree in the given direction (
descend tree dir), find all leaves from that point (findAllLeaves), and then prepend the direction chosen to each of those subpaths (map (dir:)).So why the base case
[[]]? Well, think about the case just above the base case. So, for example,findAllLeaves (F N N). When we choosedir = L, we evaluate the second line:Descending left gives us just
NThen we’ve hit the base case:
Now can you see why we have that weird base case? A list with an empty list inside? Because we are going to map
(L:)onto it, in other words, prependLto each list in the outer list. This results in:We get a similar result when
dir = R.So then the list monad concatenates those together
And we end up with
If any of this is still unclear, please let me know in a comment and I’ll try to clarify.