Let's take things one case at a time, using exactly the cases from the data definition of Btree
. That is, since
data Btree a = ND | Data a | Branch (Btree a) (Btree a)
then we will consider exactly the following shapes of trees, and no others:
ND
Data d
Branch l r
Let's begin.
findpath f x ND = {- TODO -}
Recall the specification:
Function findpath which given a function f, some data x and a tree t, returns the list of paths (possibly empty) in t to the nodes of the form Data d where f d is equal to x.
(I've assumed where you wrote "Node d", you meant "Data d", to align with your definition of trees, and changed "lists" to "list".)
In the current case, we have f
and x
as described, and t = ND
. Substituting these in the description of what we should return, we get:
the list of paths in ND to the nodes of the form Data d where ...
Since ND
does not contain any nodes of the form Data d
, there are no such paths. So:
findpath f x ND = []
Next case:
findpath f x (Data d) = {- TODO -}
Now we have t = Data d
. Revising the spec again, we must return
the list of paths in Data d
to the nodes of the form Data d where f d is equal to x.
Okay, well, then we must check whether f d
is equal to x
or not, hey?
findpath f x (Data d) = if f d == x
then {- TODO -}
else {- TODO -}
If f d == x
, then there's exactly one path to a node of the form Data d where f d is equal to x -- namely, the empty path. If not f d == x
, then there's no such paths. So:
findpath f x (Data d) = if f d == x
then [[]]
else []
And the last case:
findpath f x (Branch l r) = {- TODO -}
Revising the specification once again, now with t = Branch l r
, we must return
the list of paths in Branch l r
to the nodes of the form Data d where f d is equal to x.
Now you may feel a little bit stuck. After all, l
and r
are so general, that it's hard to know whether there are paths into them to nodes of the form Data d, right? So how can you discover whether there's a path into Branch l r
that eventually ends at a Data d node? Of course, if there were only a way to find out the answer to those two subquestions, perhaps we could augment those paths, hey?
Luckily, we have a function that answers the subquestion: findpath
itself. So let's answer the subquestions, and then think about what to do.
findpath f x (Branch l r) = {- TODO -} where
pathsInL = findpath f x l
pathsInR = findpath f x r
Okay, so we have some paths in the tree l
that lead to nodes of the form Data d
where f x
is equal to d
(respectively, some paths in the tree r
). How can we transform those paths to be paths in the tree Branch l r
? Easy: by prepending L
(respectively, R
) to each of the paths. Then we can combine the two collections of paths together.
At this point I am going to stop providing code: I think the key missing insight for you should already be above in the recursive skeleton provided. However, I will suggest some functions that you may find helpful while fleshing out the last little bits of the skeleton:
(:)
can be used to prepend a new Dir
to a Path
.
map
can be used to upgrade a function which modifies a single Path
into one that modifies an entire list of Path
s.
(++)
can be used to concatenate two lists of Path
s, producing a single list that has all the elements of each of its two arguments.
Give it a shot, and let us know where you next get stuck!