I have the following data type (source: http://learnyouahaskell.com/zippers):
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show, Eq, Ord)
I then have the following function, that traverses the tree and replaces a Node based on directional instructions:
data Direction = L | R deriving (Show, Eq, Ord)
type Directions = [Direction]
changeNode :: Directions -> Tree Char -> Tree Char
changeNode (L : ds) (Node x l r) = Node x (changeNode ds l) r
changeNode (R : ds) (Node x l r) = Node x l (changeNode ds r)
changeNode [] (Node _ l r) = Node 'P' r l
However I don't understand this aspect of the function:
changeNode (L : ds) (Node x l r) = Node x (changeNode ds l) r
I see that this is using recursion (changeNode ds l), but I don't understand why this is using recursion.
Does anyone have a simple explanation?
This may not be the simple explanation you were hoping for, but it may help to try working through a short example. Read the following with pencil and paper handy and try to verify everything for yourself:
changeNode [L,R]
(Node 'A' (Node 'B' Empty (Node 'C' Empty Empty)) (Node 'D' Empty Empty))
I assume you'll agree that this should go left into the Node 'B' branch and then right into the Node 'C' branch, eventually replacing the 'C' with a 'P', right?
How does it do this? Well, the above expression matches the first pattern for changeNode, the one right after its type declaration. Specifically, it matches with variable assignments: ds=[R], x='A', l=the whole Node 'B' branch, and r=the whole Node 'D' branch. Therefore, we can rewrite it using the right hand side corresponding to that matching pattern. The right hand side for the pattern is:
Node x (changeNode ds l) r
and substituting the matched variables gives:
Node 'A' (changeNode [R] (Node 'B' Empty (Node 'C' Empty Empty)))
(Node 'D' Empty Empty) -- (1)
Now do you see what's happened? The first pattern for changeNode operates by "consuming" the first letter of the direction list (which has changed from [L,R] to [R]) and sort of pushing the changeNode call down into the left branch.
Now, concentrate on the value of this recursive changeNode call. This time it matches the second pattern for changeNode (with ds=[], x='B', l=Empty, and r=(Node 'C' Empty Empty)). The RHS for this pattern is:
Node x l (changeNode ds r)
which becomes (with the appropriate subtitutions):
Node 'B' Empty (changeNode [] (Node 'C' Empty Empty))
and substituting this value back into line (1), we get:
Node 'A' (Node 'B' Empty (changeNode [] (Node 'C' Empty Empty)))
(Node 'D' Empty Empty) -- (2)
Again, see how this second call has consumed the 'R' from the direction vector and pushed the changeNode call into the right branch of Node 'B'. Finally, what's the value of this last recursive changeNode call? Well, it matches the third pattern with l=Empty and r=Empty giving the RHS value:
Node 'P' Empty Empty
and substituting in to line (2), we get:
Node 'A' (Node 'B' Empty (Node 'P' Empty Empty)) (Node 'D' Empty Empty)
which was exactly what we wanted.
Contrast all this to what would have happened if the definition had been non-recursive:
changeNode' :: Directions -> Tree Char -> Tree Char
changeNode' (L : ds) (Node x l r) = Node x l r
changeNode' (R : ds) (Node x l r) = Node x l r
changeNode' [] (Node _ l r) = Node 'P' r l
In this case, our simple example would have matched the first pattern, again, with ds=[R], x='A', l=all of Node 'B' branch, r=all of Node 'D' branch, but instead of line (1), we would have used the non-recursive right hand side "Node x l r" to get the following in place of line (1):
Node 'A' (Node 'B' Empty (Node 'C' Empty Empty)) (Node 'D' Empty Empty)
See? Without the recursive call, after changeNode' consumes the 'L', it's finished. It returns the original tree with no further processing. The recursive call is needed to keep the process moving along until the direction vector is empty and the third pattern (the only one that actually changes a node) can be applied at the right place in the tree.
So, the short explanation (which doesn't really make sense until you've worked through the above example) is that the first two, recursive patterns for changeNode are used to move the changeNode call through the tree structure to the final target node where the final pattern is applied to change the node value.
Related
I recently started using Haskell and it will probably be for a short while. Just being asked to use it to better understand functional programming for a class I am taking at Uni.
Now I have a slight problem I am currently facing with what I am trying to do. I want to build it breadth-first but I think I got my conditions messed up or my conditions are also just wrong.
So essentially if I give it
[“A1-Gate”, “North-Region”, “South-Region”, “Convention Center”, “Rectorate”, “Academic Building1”, “Academic Building2”] and [0.0, 0.5, 0.7, 0.3, 0.6, 1.2, 1.4, 1.2], my tree should come out like
But my test run results are haha not what I expected. So an extra sharp expert in Haskell could possibly help me spot what I am doing wrong.
Output:
*Main> l1 = ["A1-Gate", "North-Region", "South-Region", "Convention Center",
"Rectorate", "Academic Building1", "Academic Building2"]
*Main> l3 = [0.0, 0.5, 0.7, 0.3, 0.6, 1.2, 1.4, 1.2]
*Main> parkingtree = createBinaryParkingTree l1 l3
*Main> parkingtree
Node "North-Region" 0.5
(Node "A1-Gate" 0.0 EmptyTree EmptyTree)
(Node "Convention Center" 0.3
(Node "South-Region" 0.7 EmptyTree EmptyTree)
(Node "Academic Building2" 1.4
(Node "Academic Building1" 1.2 EmptyTree EmptyTree)
(Node "Rectorate" 0.6 EmptyTree EmptyTree)))
A-1 Gate should be the root but it ends up being a child with no children so pretty messed up conditions.
If I could get some guidance it would help. Below is what I've written so far::
data Tree = EmptyTree | Node [Char] Float Tree Tree deriving (Show,Eq,Ord)
insertElement location cost EmptyTree =
Node location cost EmptyTree EmptyTree
insertElement newlocation newcost (Node location cost left right) =
if (left == EmptyTree && right == EmptyTree)
then Node location cost (insertElement newlocation newcost EmptyTree)
right
else if (left == EmptyTree && right /= EmptyTree)
then Node location cost (insertElement newlocation newcost EmptyTree)
right
else if (left /= EmptyTree && right == EmptyTree)
then Node location cost left
(insertElement newlocation newcost EmptyTree)
else Node newlocation newcost EmptyTree
(Node location cost left right)
buildBPT [] = EmptyTree
--buildBPT (xs:[]) = insertElement (fst xs) (snd xs) (buildBPT [])
buildBPT (x:xs) = insertElement (fst x) (snd x) (buildBPT xs)
createBinaryParkingTree a b = buildBPT (zip a b)
Thank you for any guidance that might be provided. Yes I have looked at some of the similar questions I do think my problem is different but if you think a certain post has a clear answer that will help I am willing to go and take a look at it.
Here's a corecursive solution.
{-# bft(Xs,T) :- bft( Xs, [T|Q], Q). % if you don't read Prolog, see (*)
bft( [], Nodes , []) :- maplist( =(empty), Nodes).
bft( [X|Xs], [N|Nodes], [L,R|Q]) :- N = node(X,L,R),
bft( Xs, Nodes, Q).
#-}
data Tree a = Empty | Node a (Tree a) (Tree a) deriving Show
bft :: [a] -> Tree a
bft xs = head nodes -- Breadth First Tree
where
nodes = zipWith g (map Just xs ++ repeat Nothing) -- values and
-- Empty leaves...
(pairs $ tail nodes) -- branches...
g (Just x) (lt,rt) = Node x lt rt
g Nothing _ = Empty
pairs ~(a: ~(b:c)) = (a,b) : pairs c
{-
nodes!!0 = g (Just (xs!!0)) (nodes!!1, nodes!!2) .
nodes!!1 = g (Just (xs!!1)) (nodes!!3, nodes!!4) . .
nodes!!2 = g (Just (xs!!2)) (nodes!!5, nodes!!6) . . . .
................ .................
-}
nodes is the breadth-first enumeration of all the subtrees of the result tree. The tree itself is the top subtree, i.e., the first in this list. We create Nodes from each x in the input xs, and when the input
is exhausted we create Emptys by using an indefinite number of Nothings instead (the Empty leaves' true length is length xs + 1 but we don't need to care about that).
And we didn't have to count at all.
Testing:
> bft [1..4]
Node 1 (Node 2 (Node 4 Empty Empty) Empty) (Node 3 Empty Empty)
> bft [1..10]
Node 1
(Node 2
(Node 4
(Node 8 Empty Empty)
(Node 9 Empty Empty))
(Node 5
(Node 10 Empty Empty)
Empty))
(Node 3
(Node 6 Empty Empty)
(Node 7 Empty Empty))
How does it work: the key is g's laziness, that it doesn't force lt's nor rt's value, while the tuple structure is readily served by -- very lazy in its own right -- pairs. So both are just like the not-yet-set variables in that Prolog pseudocode(*), when served as 2nd and 3rd arguments to g. But then, for the next x in xs, the node referred to by this lt becomes the next invocation of g's result.
And then it's rt's turn, etc. And when xs end, and we hit the Nothings, g stops pulling the values from pairs's output altogether. So pairs stops advancing on the nodes too, which is thus never finished though it's defined as an unending stream of Emptys past that point, just to be on the safe side.
(*) Prolog's variables are explicitly set-once: they are allowed to be in a not-yet-assigned state. Haskell's (x:xs) is Prolog's [X | Xs].
The pseudocode: maintain a queue; enqueue "unassigned pointer"; for each x in xs: { set pointer in current head of the queue to Node(x, lt, rt) where lt, rt are unassigned pointers; enqueue lt; enqueue rt; pop queue }; set all pointers remaining in queue to Empty; find resulting tree in the original head of the queue, i.e. the original first "unassigned pointer" (or "empty box" instead of "unassigned pointer" is another option).
This Prolog's "queue" is of course fully persistent: "popping" does not mutate any data structure and doesn't change any outstanding references to the queue's former head -- it just advances the current pointer into the queue. So what's left in the wake of all this queuing, is the bfs-enumeration of the built tree's nodes, with the tree itself its head element -- the tree is its top node, with the two children fully instantiated to the bottom leaves by the time the enumeration is done.
Update: #dfeuer came up with much simplified version of it which is much closer to the Prolog original (that one in the comment at the top of the post), that can be much clearer. Look for more efficient code and discussion and stuff in his post. Using the simple [] instead of dfeuer's use of the more efficient infinite stream type data IS a = a :+ IS a for the sub-trees queue, it becomes
bftree :: [a] -> Tree a
bftree xs = t
where
t : q = go xs q
go [] _ = repeat Empty
go (x:ys) ~(l : ~(r : q)) = Node x l r : go ys q
---READ-- ----READ---- ---WRITE---
{-
xs = [ x x2 x3 x4 x5 x6 x7 x8 … ]
(t:q) = [ t l r ll lr rl rr llr … Empty Empty … … ]
-}
For comparison, the opposite operation of breadth-first enumeration of a tree is
bflist :: Tree a -> [a]
bflist t = [x | Node x _ _ <- q]
where
q = t : go 1 q
go 0 _ = []
go i (Empty : q) = go (i-1) q
go i (Node _ l r : q) = l : r : go (i+1) q
-----READ------ --WRITE--
How does bftree work: t : q is the list of the tree's sub-trees in breadth-first order. A particular invocation of go (x:ys) uses l and r before they are defined by subsequent invocations of go, either with another x further down the ys, or by go [] which always returns Empty. The result t is the very first in this list, the topmost node of the tree, i.e. the tree itself.
This list of tree nodes is created by the recursive invocations of go at the same speed with which the input list of values xs is consumed, but is consumed as the input to go at twice that speed, because each node has two child nodes.
These extra nodes thus must also be defined, as Empty leaves. We don't care how many are needed and simply create an infinite list of them to fulfill any need, although the actual number of empty leaves will be one more than there were xs.
This is actually the same scheme as used in computer science for decades for array-backed trees where tree nodes are placed in breadth-first order in a linear array. Curiously, in such setting both conversions are a no-op -- only our interpretation of the same data is what's changing, our handling of it, how are we interacting with / using it.
Update: the below solution is big-O optimal and (I think) pretty easy to understand, so I'm leaving it here in case anyone's interested. However, Will Ness's solution is much more beautiful and, especially when optimized a bit, can be expected to perform better in practice. It is much more worthy of study!
I'm going to ignore the fake edge labels for now and just focus on the core of what's happening.
A common pattern in algorithm design is that it's sometimes easier to solve a more general problem. So instead of trying to build a tree, I'm going to look at how to build a forest (a list of trees) with a given number of trees. I'll make the node labels polymorphic to avoid having to think about what they look like; you can of course use the same building technique with your original tree type.
data Tree a = Empty | Node a (Tree a) (Tree a)
-- Built a tree from a breadth-first list
bft :: [a] -> Tree a
bft xs = case dff 1 xs of
[] -> Empty
[t] -> t
_ -> error "something went wrong"
-- Build a forest of nonempty trees.
-- The given number indicates the (maximum)
-- number of trees to build.
bff :: Int -> [a] -> [Tree a]
bff _ [] = []
bff n xs = case splitAt n xs of
(front, rear) -> combine front (bff (2 * n) rear)
where
combine :: [a] -> [Tree a] -> [Tree a]
-- you write this
Here's a full, industrial-strength, maximally lazy implementation. This is the most efficient version I've been able to come up with that's as lazy as possible. A slight variant is less lazy but still works for fully-defined infinite inputs; I haven't tried to test which would be faster in practice.
bft' :: [a] -> Tree a
bft' xs = case bff 1 xs of
[] -> Empty
[t] -> t
_ -> error "whoops"
bff' :: Int -> [a] -> [Tree a]
bff' !_ [] = []
bff' n xs = combine n xs (bff (2 * n) (drop n xs))
where
-- The "take" portion of the splitAt in the original
-- bff is integrated into this version of combine. That
-- lets us avoid allocating an intermediate list we don't
-- really need.
combine :: Int -> [a] -> [Tree a] -> [Tree a]
combine 0 !_ ~[] = [] -- These two lazy patterns are just documentation
combine _k [] ~[] = []
combine k (y : ys) ts = Node y l r : combine (k - 1) ys dropped
where
(l, ~(r, dropped)) = case ts of -- This lazy pattern matters.
[] -> (Empty, (Empty, []))
t1 : ts' -> (t1, case ts' of
[] -> (Empty, [])
t2 : ts'' -> (t2, ts''))
For the less-lazy variant, replace (!l, ~(!r, dropped)) with (!l, !r, dropped) and adjust the RHS accordingly.
For true industrial strength, forests should be represented using lists strict in their elements:
data SL a = Cons !a (SL a) | Nil
And the pairs in the above (l, ~(r, dropped)) should both be represented using a type like
data LSP a b = LSP !a b
This should avoid some (pretty cheap) run-time checks. More importantly, it makes it easier to see where things are and aren't getting forced.
The method that you appear to have chosen is to build the tree up backwards: from bottom-to-top, right-to-left; starting from the last element of your list. This makes your buildBPT function look nice, but requires your insertElement to be overly complex. To construct a binary tree in a breadth-first fashion this way would require some difficult pivots at every step past the first three.
Adding 8 nodes to the tree would require the following steps (see how the nodes are inserted from last to first):
. 4
6 6
8 7 8 . .
. .
3
7 4 5
8 . 6 7 8 .
6 2
7 8 3 4
5 6 7 8
5
6 7 1
8 . . . 2 3
4 5 6 7
8 . . . . . . .
If, instead, you insert the nodes left-to-right, top-to-bottom, you end up with a much simpler solution, requiring no pivoting, but instead some tree structure introspection. See the insertion order; at all times, the existing values remain where they were:
. 1
2 3
1 4 5 . .
. .
1
1 2 3
2 . 4 5 6 .
1 1
2 3 2 3
4 5 6 7
1
2 3 1
4 . . . 2 3
4 5 6 7
8 . . . . . . .
The insertion step has an asymptotic time complexity on the order of O(n^2) where n is the number of nodes to insert, as you are inserting the nodes one-by-one, and then iterating the nodes already present in the tree.
As we insert left-to-right, the trick is to check whether the left sub-tree is complete:
if it is, and the right sub-tree is not complete, then recurse to the right.
if it is, and the right sub-tree is also complete, then recurse to the left (starting a new row).
if it is not, then recurse to the left.
Here is my (more generic) solution:
data Tree a = Leaf | Node a (Tree a) (Tree a)
deriving (Eq, Show)
main = do
let l1 = ["A1-Gate", "North-Region", "South-Region", "Convention Center",
"Rectorate", "Academic Building1", "Academic Building2"]
let l2 = [0.0, 0.5, 0.7, 0.3, 0.6, 1.2, 1.4, 1.2]
print $ treeFromList $ zip l1 l2
mkNode :: a -> Tree a
mkNode x = Node x Leaf Leaf
insertValue :: Tree a -> a -> Tree a
insertValue Leaf y = mkNode y
insertValue (Node x left right) y
| isComplete left && nodeCount left /= nodeCount right = Node x left (insertValue right y)
| otherwise = Node x (insertValue left y) right
where nodeCount Leaf = 0
nodeCount (Node _ left right) = 1 + nodeCount left + nodeCount right
depth Leaf = 0
depth (Node _ left right) = 1 + max (depth left) (depth right)
isComplete n = nodeCount n == 2 ^ (depth n) - 1
treeFromList :: (Show a) => [a] -> Tree a
treeFromList = foldl insertValue Leaf
EDIT: more detailed explanation:
The idea is to remember in what order you insert nodes: left-to-right first, then top-to-bottom. I compressed the different cases in the actual function, but you can expand them into three:
Is the left side complete? If not, then insert to the left side.
Is the right side as complete as the left side, which is complete? If not, then insert to the right side.
Both sides are full, so we start a new level by inserting to the left side.
Because the function fills the nodes up from left-to-right and top-to-bottom, then we always know (it's an invariant) that the left side must fill up before the right side, and that the left side can never be more than one level deeper than the right side (nor can it be shallower than the right side).
By following the growth of the second set of example trees, you can see how the values are inserted following this invariant. This is enough to describe the process recursively, so it extrapolates to a list of any size (the recursion is the magic).
Now, how do we determine whether a tree is 'complete'? Well, it is complete if it is perfectly balanced, or if – visually – its values form a triangle. As we are working with binary trees, then the base of the triangle (when filled) must have a number of values equal to a power of two. More specifically, it must have 2^(depth-1) values. Count for yourself in the examples:
depth = 1 -> base = 1: 2^(1-1) = 1
depth = 2 -> base = 2: 2^(2-1) = 2
depth = 3 -> base = 4: 2^(3-1) = 4
depth = 4 -> base = 8: 2^(4-1) = 8
The total number of nodes above the base is one less than the width of the base: 2^(n-1) - 1. The total number of nodes in the complete tree is therefore the number of nodes above the base, plus those of the base, so:
num nodes in complete tree = 2^(depth-1) - 1 + 2^(depth-1)
= 2 × 2^(depth-1) - 1
= 2^depth - 1
So now we can say that a tree is complete if it has exactly 2^depth - 1 non-empty nodes in it.
Because we go left-to-right, top-to-bottom, when the left side is complete, we move to the right, and when the right side is just as complete as the left side (meaning that it has the same number of nodes, which is means that it is also complete because of the invariant), then we know that the whole tree is complete, and therefore a new row must be added.
I originally had three special cases in there: when both nodes are empty, when the left node is empty (and therefore so was the right) and when the right node is empty (and therefore the left could not be). These three special cases are superseded by the final case with the guards:
If both sides are empty, then countNodes left == countNodes right, so therefore we add another row (to the left).
If the left side is empty, then both sides are empty (see previous point).
If the right side is empty, then the left side must have depth 1 and node count 1, meaning that it is complete, and 1 /= 0, so we add to the right side.
So, this tree is NOT a Binary Search Tree. It is in no particular order, and is just in this order for quick access to specific indices (nth element), rather than whether an element exists or not.
The form of the Tree is like so:
data Tree a = Leaf a | Node Int (Tree a) (Tree a) deriving Show
For this specific tree, the "Int" from the Node constructor is the number of elements underneath that node (or number of leaves).
Using this structure, I copied parts of the Tree functions available in a lecture I found online (that I slightly modified when trying to understand):
buildTree :: [a] -> Tree a
buildTree = growLevel . map Leaf
where
growLevel [node] = node
growLevel l = growLevel $ inner l
inner [] = []
inner (e1:e2:rest) = e1 <> e2 : inner rest
inner xs = xs
join l#(Leaf _) r#(Leaf _) = Node 2 l r
join l#(Node ct _ _) r#(Leaf _) = Node (ct+1) l r
join l#(Leaf _) r#(Node ct _ _) = Node (ct+1) l r
join l#(Node ctl _ _) r#(Node ctr _ _) = Node (ctl+ctr) l r
And I was able to create some basic functions for moving through a tree. I made one that finds the nth element and returns it. I also made a Path datatype and implemented a function to return the path (in left and rights) to a specific index, and one function that can travel through a path and return that Node/Leaf.
Now, what I would like to make is a delete function. The problem here is with the fact that the tree is "leafy", or at least that is what is causing me difficulties.
If I end up with a Leaf at the deletion path, there is no "Null" or equivalent item to replace it with. Additionally, if I try to stop at the last path (like [L]), and check if that's a Node or not, then if it's a leaf replace the whole node with the opposite side etc., I run into the problem of changing the whole tree to reflect that change, not just return the end of the deletion, and change all the numbers from the tree to reflect the change in leaves.
I would like order to be preserved when deleting an item, like if you were to use a list as a simpler example:
del 4 [1, 2, 3, 4, 5, 6, 7] = [1, 2, 3, 4, 6, 7]
If there is a simpler way to structure the Tree (that still can contain duplicate elements and preserve order) what is it?
Is there some way to delete an element using this method?
If I ... replace the whole node with the opposite side ... I run into the problem of changing the whole tree to reflect that change, not just return the end of the deletion, and change all the numbers from the tree to reflect the change in leaves.
Well, not the whole tree - just the path from the deleted node back to the root. And isn't that exactly what you want?
I guess the first step would be, define what you mean by "delete". Should the indexes of undeleted nodes remain the same after deletion, or should nodes after the deleted node have their indexes reduced by one? That is, given:
tree :: [a] -> Tree a
-- get and del both 0-indexed, as in your example
get :: Int -> Tree a -> Maybe a
del :: Int -> Tree a -> Tree a
then of course
get 5 $ tree [1..7]
should yield Just 6. But what about
get 5 . del 4 $ tree [1..7]
? If you want this to still yield Just 6 (there is a "blank" spot in your tree where 5 used to be), that is a rather tricky concept, I think. You can put Nothings in to make space, if you define Leaf (Maybe a) instead of Leaf a, but this only papers over the problem: inserts will still shift indices around.
I think it is much simpler for this to yield Just 7 instead, making del 4 $ tree [1..7] the same as tree [1,2,3,4,6,7]. If this is your goal, then you simply must renumber all the nodes on the path from the deleted node back to the root: there is no getting around the fact that they all have one fewer leaf descendant now. But the other nodes in the tree can remain untouched.
For reference, one possible implementation of del:
count :: Tree a -> Int
count (Leaf _) = 1
count (Node s _ _) = s
del :: Int -> Tree a -> Maybe (Tree a)
del n t | n < 0 || n >= size || size <= 1 = Nothing
| otherwise = go n t
where size = count t
go n (Leaf _) = Nothing
go n (Node s l r) | n < size = reparent flip l r
| otherwise = reparent id r l
where reparent k c o = pure . maybe o (k (Node (s - 1)) o) $ go n c
size = count l
If I end up with a Leaf at the deletion path, there is no "Null" or equivalent item to replace it with.
Well, make one :). This is what Maybe is for: when you delete an element from a Tree, you cannot expect to get a Tree back, because Tree is defined to be nonempty. You need to explicitly add the possibility of emptiness by wrapping in Maybe. Deletion may also fail with an out-of-bounds error, which I represent with Either Int and incorporate into the logic.
delete :: Int -> Tree a -> Either Int (Maybe (Tree a))
delete i t | i >= max = Left (i - max) where max = count t
delete _ (Leaf _) = Right Nothing
delete i (Node n l r) = case delete i l of
Left i' -> Just <$> maybe l (Node (n - 1) l) <$> delete i' r
Right l' -> Right $ Just $ maybe r (\x -> Node (n - 1) x r) l'
Where count is as I recommended in the comments:
count :: Tree a -> Int
count (Leaf _) = 1
count (Node n _ _) = n
I am trying to convert postfix expression to binary tree. My function takes as argument a list of tokens (strings).
Everytime I give the function any input, debugger writes a message: Non-exhaustive patterns in function "add".
My idea was: read a token after token and determine, if it is an operator or an operand. If it is operand, don't save any node to the tree and store the number to the stack. Otherwise I create a node with an operator, pop symbols from stack, set them as children of new node and push the operator to stack.
If the list of strings is empty, functions print the binary tree.
Would someone explain to me, why the function gives non-exhaustive patterns error and how can I fix the function?
data Tree = Leaf String | Empty | Node Tree String Tree deriving (Show)
add :: Tree -> [String] -> [Tree] -> Tree
add (Node l v p) [] stack = (Node l v p)
add Empty (x:xs) []
| x `elem` ["*","-","+"] = add (Leaf x) xs [Leaf x]
| otherwise = add Empty xs [Leaf x]
add Empty (x:xs) (a:b:bs)
| x `elem` ["*","-","+"] = add (Node b x a) xs (Leaf x:a:b:bs)
| otherwise = add Empty xs (Leaf x:a:b:bs)
add (Leaf x) token (a:b:bs)
| x `elem` ["*","-","+"] = add (Node b x a) token (Leaf x:bs)
| otherwise = Leaf x
add (Node l v p) (x:xs) (a:b:bs)
| x `elem` ["*","-","+"] = add (Node b x a) xs (Leaf x:bs)
| otherwise = add (Node l v p) xs (Leaf x:a:b:bs)
parse :: String -> Tree
parse input = add Empty (words (toPostfix input)) []
I've managed to reproduce the error by simple example:
add Empty ["10", "1", "+"] []
The program successfully adds Leaf "10" to the stack, but can't add Leaf "1" to the stack, because the add is called with the following args:
add Empty ["1", "+"] [Leaf "10"]
But it doesn't match any pattern, because add Empty (x:xs) (a:b:bs) expects the third argument to have two Tree elements and a list. Therefore, a pattern that matches third argument as a list with one element is needed. For example, adding:
add Empty (x:xs) [a] = add Empty xs (Leaf x:[a])
fixes the error and prints the following:
Node (Leaf "10") "+" (Leaf "1")
Hope it'll help you to continue with the task, unless you've already solved it :)
Given the following data type definition:
data FormTree = Empty | Node FormTree FormTree deriving Show
I want to write a function which generates an infinite list containing all possible trees sorted after length e.g. the amount of nodes.
The following code almost does what I need but it only descends the tree on the right side by inserting additional nodes every time but I need it to alternate between both sides.
allPossibleTrees :: [FormTree]
allPossibleTrees = Empty : [Node x y | x <- recursive, y <- recursive]
where recursive = allPossibleTrees
Executing
take 5 allPossibleTrees
gives:
[Empty,Node Empty Empty,Node Empty (Node Empty Empty),Node Empty (Node Empty (Nodes Empty Empty)),Node Empty (Node Empty (Node Empty (Node Empty Empty)))]
but it should be something like:
[Empty,Node Empty Empty,Node (Node Empty Empty) Empty,Node Empty (Node Empty Empty),Node (Node Empty Empty) (Node Empty Empty)]
Here's a nice trick, reminiscent of the standard Fibonacci numbers trick. We'll build a lazy list; each member of the list will be a list of all trees with a given number of nodes. There's just one tree with no nodes, Empty, and that will serve as our base case. To build all the trees with n nodes, we'll assume we already know how to build trees with 0, 1, 2, ..., n-1 nodes. Then we'll just non-deterministically choose a pairing of those that sums to n-1 and stuck a Node on top.
In code:
import Control.Monad
import Data.List
sizes :: [[FormTree]]
sizes = [Empty] : (map go . drop 1 . inits) sizes where
go smaller = do
(ls, rs) <- zip smaller (reverse smaller)
liftM2 Node ls rs
Then we can simply define allPossibleTrees = concat sizes if that's wanted. The first few entries:
*Main> mapM_ print (take 4 sizes)
[Empty]
[Node Empty Empty]
[Node Empty (Node Empty Empty),Node (Node Empty Empty) Empty]
[Node Empty (Node Empty (Node Empty Empty)),Node Empty (Node (Node Empty Empty) Empty),Node (Node Empty Empty) (Node Empty Empty),Node (Node Empty (Node Empty Empty)) Empty,Node (Node (Node Empty Empty) Empty) Empty]
We can do a quick sanity check:
*Main> take 10 (map length sizes)
[1,1,2,5,14,42,132,429,1430,4862]
...which is indeed the first ten Catalan numbers, so we probably got it right!
The list comprehension
[ (x,y) | x<-[1..] , y<-[1..] ]
starts by considering x=1 and building all the pairs (1,y) for all the possible ys. Then follows with x=2 and all the (2,y) pairs. and so on.
However, there are infinitely many (1,y) pairs, so x=2 will only be considered after an infinite amount of time -- that is, not at all.
Your code suffers from the same problem.
To see a possible solution, you can refer to this related question exploiting the Omega monad to achieve a fair scheduling among all the cases.
One way is to keep track of the size of the tree (i.e. the number of Node constructors used.)
Suppose you had a function like this which returned the trees using exactly n Node constructors:
treesOfSize :: Int -> [FormTree]
Then allTrees could be defined as:
allTrees = concatMap treesOfSize [0..]
The definition of treesOfSize can be recursively defined which I'll let you figure out:
treesOfSize 0 = [Empty]
treesOfSize n = [ Node t1 t2 | ... ]
control-monad-omega library seems to do the trick with your original code:
{-# LANGUAGE MonadComprehensions #-}
import Control.Monad.Omega
data Empty = Empty | Node Empty Empty deriving Show
allPossibleTrees :: [Empty]
allPossibleTrees = Empty :
runOmega [Node x y | x <- each allPossibleTrees, y <- each allPossibleTrees]
First 10 trees look good to me:
*Main> mapM_ print $ take 10 allPossibleTrees
Empty
Node Empty Empty
Node Empty (Node Empty Empty)
Node (Node Empty Empty) Empty
Node Empty (Node Empty (Node Empty Empty))
Node (Node Empty Empty) (Node Empty Empty)
Node (Node Empty (Node Empty Empty)) Empty
Node Empty (Node (Node Empty Empty) Empty)
Node (Node Empty Empty) (Node Empty (Node Empty Empty))
Node (Node Empty (Node Empty Empty)) (Node Empty Empty)
So I am trying to add consecutive numbers to the elements in a BST strictly using recursion (no standard prelude functions). Here is what I have so far:
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
leaf x = Node x Empty Empty
number' :: Int -> Tree a -> Tree (Int, a)
number' a Empty = Empty
number' a (Node x xl xr) = Node (a,x) (number' (a+1) xl) (number' (a+1) xr)
number :: Tree a -> Tree (Int, a)
number = number' 1
number' is an auxiliary function that carries around "a" as a counter. It should add 1 to each recursive call, so I am not sure why it is doing what it is doing.
As of now the level of the element is assigned to each element. I would like the first element to be assigned 1, the element to the left of that 2, the element to the left of that 3, etc. Each element should get a+1 assigned to it and no number should be repeated. Thanks in advance.
I want to first explain why the code in the question assigns level numbers. This will lead us directly to two different solutions, one passed on caching, one based on doing two traversals at once. Finally, I show how the second solution relates to the solutions provided by other answers.
What has to be changed in the code from the question?
The code in the question assigns the level number to each node. We can understand why the code behaves like that by looking at the recursive case of the number' function:
number' a (Node x xl xr) = Node (a,x) (number' (a+1) xl) (number' (a+1) xr)
Note that we use the same number, a + 1, for both recursive calls. So the root nodes in both subtrees will get assigned the same number. If we want each node to have a different number, we better pass different numbers to the recursive calls.
What number should we pass to the recursive call?
If we want to assign the numbers according to a left-to-right pre-order traversal, then a + 1 is correct for the recursive call on the left subtree, but not for the recursive call on the right subtree. Instead, we want to leave out enough numbers to annotate the whole left subtree, and then start annotating the right subtree with the next number.
How many numbers do we need to reserve for the left subtree? That depends on the subtree's size, as computed by this function:
size :: Tree a -> Int
size Empty = 0
size (Node _ xl xr) = 1 + size xl + size xr
Back to the recursive case of the number' function. The smallest number annotated somewhere in the left subtree is a + 1. The biggest number annotated somewhere in the left subtree is a + size xl. So the smallest number available for the right subtree is a + size xl + 1. This reasoning leads to the following implementation of the recursive case for number' that works correctly:
number' :: Int -> Tree a -> Tree (Int, a)
number' a Empty = Empty
number' a (Node x xl xr) = Node (a,x) (number' (a+1) xl) (number' (a + size xl + 1) xr)
Unfortunately, there is a problem with this solution: It is unnecessarily slow.
Why is the solution with size slow?
The function size traverses the whole tree. The function number' also traverses the whole tree, and it calls size on all left subtrees. Each of these calls will traverse the whole subtree. So overall, the function size gets executed more than once on the same node, even though it always returns the same value, of course.
How can we avoid traversing the tree when calling size?
I know two solutions: Either we avoid traversing the tree in the implementation of size by caching the sizes of all trees, or we avoid calling size in the first place by numbering the nodes and computing the size in one traversal.
How can we compute the size without traversing the tree?
We cache the size in every tree node:
data Tree a = Empty | Node Int a (Tree a) (Tree a) deriving (Show)
size :: Tree a -> Int
size Empty = 0
size (Node n _ _ _) = n
Note that in the Node case of size, we just return the cached size. So this case is not recursive, and size does not traverse the tree, and the problem with our implementation of number' above goes away.
But the information about the size has to come from somewhere! Everytime we create a Node, we have to provide the correct size to fill the cache. We can lift this task off to smart constructors:
empty :: Tree a
empty = Empty
node :: a -> Tree a -> Tree a -> Tree a
node x xl xr = Node (size xl + size xr + 1) x xl xr
leaf :: a -> Tree a
leaf x = Node 1 x Empty Empty
Only node is really necessary, but I added the other two for completeness. If we always use one of these three functions to create a tree, the cached size information will always be correct.
Here is the version of number' that works with these definitions:
number' :: Int -> Tree a -> Tree (Int, a)
number' a Empty = Empty
number' a (Node _ x xl xr) = node (a,x) (number' (a+1) xl) (number' (a + size xl + 1) xr)
We have to adjust two things: When pattern matching on Node, we ignore the size information. And when creating a Node, we use the smart constructor node.
That works fine, but it has the drawback of having to change the definition of trees. On the one hand, caching the size might be a good idea anyway, but on the other hand, it uses some memory and it forces the trees to be finite. What if we want to implement a fast number' without changing the definition of trees? This brings us to the second solution I promised.
How can we number the tree without computing the size?
We cannot. But we can number the tree and compute the size in a single traversal, avoiding the multiple size calls.
number' :: Int -> Tree a -> (Int, Tree (Int, a))
Already in the type signature, we see that this version of number' computes two pieces of information: The first component of the result tuple is the size of the tree, and the second component is the annotated tree.
number' a Empty = (0, Empty)
number' a (Node x xl xr) = (sl + sr + 1, Node (a, x) yl yr) where
(sl, yl) = number' (a + 1) xl
(sr, yr) = number' (a + sl + 1) xr
The implementation decomposes the tuples from the recursive calls and composes the components of the result. Note that sl is like size xl from the previous solution, and sr is like size xr. We also have to name the annotated subtrees: yl is the left subtree with node numbers, so it is like number' ... xl in the previous solution, and yr is the right subtree with node numbers, so it is like number' ... xr in the previous solution.
We also have to change number to only return the second component of the result of number':
number :: Tree a -> Tree (Int, a)
number = snd . number' 1
I think that in a way, this is the clearest solution.
What else could we improve?
The previous solution works by returning the size of the subtree. That information is then used to compute the next available node number. Instead, we could also return the next available node number directly.
number' a Empty = (a, Empty)
number' a (Node x xl xr) = (ar, Node (a, x) yl yr) where
(al, yl) = number' (a + 1) xl
(ar, yr) = number' al xr
Note that al is like a + sl + 1 in the previous solution, and ar is like a + sl + sr + 1. Clearly, this change avoids some additions.
This is essentially the solution from Sergey's answer, and I would expect that this is the version most Haskellers would write. You could also hide the manipulations of a, al and ar in a state monad, but I don't think that really helps for such a small example. The answer by Ankur shows how it would look like.
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
number :: Tree a -> Tree (Int, a)
number = fst . number' 1
number' :: Int -> Tree a -> (Tree (Int, a), Int)
number' a Empty = (Empty, a)
number' a (Node x l r) = let (l', a') = number' (a + 1) l
(r', a'') = number' a' r
in (Node (a, x) l' r', a'')
*Tr> let t = (Node 10 (Node 20 (Node 30 Empty Empty) (Node 40 Empty Empty)) (Node 50 (Node 60 Empty Empty) Empty))
*Tr> t
Node 10 (Node 20 (Node 30 Empty Empty) (Node 40 Empty Empty)) (Node 50 (Node 60 Empty Empty) Empty)
*Tr> number t
Node (1,10) (Node (2,20) (Node (3,30) Empty Empty) (Node (4,40) Empty Empty)) (Node (5,50) (Node (6,60) Empty Empty) Empty)
As suggested by comments in your question that each call to number should return a integer also which needs to be further used for next set of nodes. This makes the signature of the function to:
Tree a -> Int -> (Tree (Int,a), Int)
Looking at the last part of it, it looks like a candidate for State monad i.e state -> (Val,state).
Below code shows how you can do this using State monad.
import Control.Monad.State
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
myTree :: Tree String
myTree = Node "A" (Node "B" (Node "D" Empty Empty) (Node "E" Empty Empty)) (Node "C" (Node "F" Empty Empty) (Node "G" Empty Empty))
inc :: State Int ()
inc = do
i <- get
put $ i + 1
return ()
number :: Tree a -> State Int (Tree (Int,a))
number Empty = return Empty
number (Node x l r) = do
i <- get
inc
l' <- number l
r' <- number r
return $ Node (i,x) l' r'
main = do
putStrLn $ show (fst (runState (number myTree) 1))