Zipping tuples inside Haskell tree - haskell

I'm seeking any suggestion how to solve a problem with a binary search tree in Haskell. It has declaration as follows:
data TreeMap v = Leaf | Node { pair::(Integer, v), l::TreeMap v, r::TreeMap v} deriving (Show, Read, Eq, Ord)
Now I want to zip all pairs to have them as array elements. My solution so far is
listMyTuples :: TreeMap v -> [(Integer, v)]
listMyTuples Leaf = []
listMyTuples (Node pair Leaf tree2) = pair : listMyTuples tree2
listMyTuples (Node pair tree1 Leaf) = pair : listMyTuples tree1
...other pattern matching needed
I'm barely to complete that due to some lack of comprehension what to do in a case of missing leafs. So, how to make some kind of functional brigde between two subtrees to get it right?

Why pattern match on the subtrees? You can just use Node pair t1 t2. Indeed:
listFromTree :: TreeMap v -> [(Integer, v)]
listFromTree Leaf = []
listFromTree (Node pair t1 t2) = pair : listFromTree t1 ++ listFromTree t2
Here we use (++) :: [a] -> [a] -> [a] to append two lists together.
In case one of the two subtrees is a Leaf, then this will result in an empty list, and appending with an empty list, results in the other list.

Related

Inserting list into Binary Tree in Haskell

Basically, I'm trying to insert elements from the list into the binary tree one by one, or that's what I thought it should be done when inserting list to the tree.
Here is my tree for inserting:
data Tree = EmptyTree | Node Integer Tree Tree deriving (Show, Eq, Ord)
insertElement x EmptyTree = Node x EmptyTree EmptyTree
insertElement x (Node a left right) = if x == a
then (Node x left right)
else if x < a
then (Node a (insertElement x left) right)
else
Node a left (insertElement x right)
and I thought I could use map to get elements from list and insert it into the list.
Something like this: inserter x = map (insertElement x EmptyTree)
where I get list with inserter and insert it into the list.
But, this code is pretty much incorrect I think, and I was wondering how can I do this?
If you would use inserter xs = map (`insertElement` EmptyTree) you will create a list of trees where each item is inserted once.
What you can do is use foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b or foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b to each time pass the accumulator, the thus far build up list, and thus insert the next item, so:
inserter :: Foldable f => f Integer -> Tree
inserter = foldr insertElement EmptyTree
or:
inserter :: Foldable f => f Integer -> Tree
inserter = foldl (flip insertElement) EmptyTree
It might however make more sense to allow to specify the base tree, and thus using inserter to insert a Foldable of items to a Tree that might already contain items, for example:
inserter :: Foldable f => Tree -> f Integer -> Tree
inserter = foldl (flip insertElement)

Can't figure out how to properly type my N-ary tree

I made the following N-ary tree data type:
data Tree a = Leaf a | Node a [Tree a] deriving (Show)
with the following method:
listLeaf::Tree a -> [a]
listLeaf (Leaf a) = [a]
listLeaf (Node a (l:list)) = concat $ listLeaf l
I'm trying to make listLeaf so that it gives me a list that contains each element of a leaf inside my tree. This means that if I have the following tree: Node 3 [Leaf 1, Leaf 2, Node 1 [Leaf 3]], my objective would be to get [1,2,3].
As you probably noticed the type of my function doesn't add up because it expects a list of a, but I'm giving it a list of lists.
Can't wrap my head around how I can have the base case (leaf) return me a type [a] and at the same time have the Node case give me the same kind of type. I feel like I need to use a higher order function aside from concat, but I got no clue.
Any hints?
You are here only calling listLeaf on l, the first element of the list, so you will only obtain the leftmost leaf. Furthermor concat then does not make much sense, ince you have a list of values, not a list of lists of values.
You can use concatMap :: (a -> [b]) -> [a] -> [b] to perform a mapping on all elements and concatenate the lists of the results, so:
listLeaf :: Tree a -> [a]
listLeaf (Leaf a) = [a]
listLeaf (Node _ cs) = concatMap listLeaf cs

General Tree in Haskell = Rose Tree? Postoder for a rose tree?

I was supposed to create a data structure for a Tree, where every Node has an undefined amount of branches. I am guessing this will be a rose tree.
data GTree a = Node a [GTree a]
Now I am supposed to write a postorderG function that will give me a list of all my elements in my general in a postorder sequence
I wrote this but it does not seem right... Could someone help me?
postorderG :: GTree a -> [a]
postorderG (Node x l r) = postorder l ++ postorder r ++ [GTree x]
GTree is a type constructor, not a data constructor; a tree would be created with Node x [], not GTree x.
However, you don't need to create a tree at all here. You just need a the value stored at the root of the input tree for the final list in the return value.
postorderG :: GTree a -> [a]
postorderG (Node x ch) = concatMap postorderG ch -- [a]
++ [x] -- [a], not [GTree a]
If you wanted to, you could create a singleton tree to append to ch, the apply postOrderG to each child and the new singleton in order.
postorderG (Node x ch) = concatMap postorderG (ch ++ [Node x []])
Taking advantage of the [] monad instead of using concatMap, the RHS would look like either
(ch >>= postorderG) ++ [x]
or
(ch ++ [Node x []]) >>= postorderG

Find all leafes of a binary searchtree by folding

I got the task of getting all leafs from a binary tree of this datatype:
data Bintree el = Empty |
Tree {left :: Bintree el, node :: el, right :: Bintree el} deriving Show
Now I have this Treefold function which works perfectly in tests:
binTreeFold :: (a -> b -> a -> a) -> a -> Bintree b -> a
binTreeFold f el Empty = el
binTreeFold f el tree#(Tree leftTree node rightTree) = f (binTreeFold f el leftTree) node (binTreeFold f el rightTree)
And I try to get all leafs but somehow it simply doesnt work (Compile issues mentioned below):
leavesWithFold :: Bintree a -> [a]
leavesWithFold Empty = []
leavesWithFold tree = binTreeFold (\left -> \node -> \right -> if (checkIfTreeIsLeaf node) then left ++ [node] ++ right else left ++ [] ++ right) [] tree
using the following function:
checkIfTreeIsLeaf :: Bintree a -> Bool
checkIfTreeIsLeaf Empty = False
checkIfTreeIsLeaf (Tree Empty node Empty) = True
checkIfTreeIsLeaf _ = False
The compiler tells me
Couldn't match type `a' with `Bintree a0'
But in former functions the use of
left ++ [node] ++ right
Was working perfectly fine. Have you any idea what I did wrong and probably what I could change?
Best Whishes
Well typically the idea of a using a fold function is that it does all the work for you. So by writing a function that branches into an Empty case and a tree case, this is already a bit strange.
A recursive approach
But let us simply start with a recursive approach. Forget about folding, etc. for now. How would we generate a list of leaves in general?
Well there are basically three cases here:
in case we encounter an Empty, then we return the empty list, since Empty is not a leaf, and we are supposed to return all leaves, so:
leaves Empty = []
in case we encounter a Tree with Empty both as left and right subtree, we know that that Tree is a leaf, so we return the element it carries, as a list:
leaves (Tree Empty x Empty) = [x]
in case one of the two subtrees (or both) are not Empty, we recursively would call the leaves function, and concatenate the two together:
leaves (Tree l _ r) = leaves l ++ leaves r
So now in full we got:
leaves :: Bintree a -> [a]
leaves Empty = []
leaves (Tree Empty x Empty) = [x]
leaves (Tree l x r) = leaves l ++ leaves r
How to detect through recursion that this is a leaf
We of course can not do that with the binTreeFold approach. But can't we detect whether a tree is in fact a leaf? In case the two recursive calls both result in an empty list, we know that the current Bintree is in fact a leaf. Indeed: if the left (and right) subtree are Empty, they result in empty lists. And in case these are not empty, then these either are leaves, that will recursively produce a singleton list, or those are not Trees with descendants, that will eventually lead to leaves, and therefore to non-empty lists.
Encoding this in the fold function
So we an first take a look at the recursive calls, and then based on the fact whether these are both empty lists, either return a singleton list with the leaf element, or concatenate the two lists together, like:
f [] x [] = [x]
f l _ r = l ++ r
Or using this in the binTreeFold function:
leavesWithFold :: Bintree a -> [a]
leavesWithFold = binTreeFold f []
where f [] x [] = [x]
f l _ r = l ++ r

Haskell Tree help

Could anyone please help me with my assignment questions? I've done most of it but I'm still stuck on these 3 questions.
Here is the question:
Consider the following types of search trees and balanced trees
data STree = Leaf | Node STree Int STree
data Btree = Tip Int | Branch Btree Btree
whose constructors are subject to the following constraints:
Values of the form Node left n right must have all integers in left being at most n and all integers in right being greater than n.
Values of the form Branch left right must have a difference between the numbers of integers in left and right of at most one.
a) Define a recursive function stree :: [Int] -> STree that constructs a search tree from a list of integers.
b) Define a recursive function btree :: [Int] -> BTree that constructs a balanced tree from a non-empty list of integers.
c) Using merge, define a recursive function collapse :: BTree -> [Int] that collapses a balanced tree to give a sorted list of integers.
Please help me!!!
Thanks very much in advance!
Don't want to take all the fun, but here is my go at part a.
stree :: [Int] -> Stree
stree [] = Leaf
stree (x:xs) = let (left, right) = partition (<= x) xs
in Stree (stree left) x (stree right)
It just takes the components that should be on the left and right and recursively builds the subtrees for each.
Assuming the use of sort is legit, then I'm pretty certain this works for part b.
btree :: [Int] -> Btree
btree (x:[]) = Tip x
btree xs = let len = length xs `div` 2
ys = sort xs
in Branch (btree (take len ys)) (btree (drop len ys))
stree = foldr insert Leaf
where insert :: Int -> STree -> STree
insert i (Node l i' r) | i <= i' = Node (insert i l) i' r
| otherwise = Node l i' (insert i r)
insert i (Leaf) = Node Leaf i Leaf
This isn't a very efficient solution, nor does it produce a very balanced tree, but it's a good example of how to iteratively build a data structure in Haskell. Using foldr to handle the iteration for us, we insert one element at a time into the tree, passing the new tree into the function that builds the next. We descend through the tree, until we find a leaf, and replace that Leaf with a Node to hold the given value.
These are recursive data structures. Let's start with the Search Tree:
data STree = Leaf | Node STree Int STree
and all values in the left must be less than the parent, which must be less than all values in the right. Can you write down the answers for stree [] and stree [x]? How far can you go?
I'll start:
stree [] = Leaf
stree [x] = Node Leaf x Leaf
stree ([x,y]) = if x < y then Node Leaf x (Node Leaf y Leaf) else Node (Node Leaf y Leaf) x Leaf
That sort of nested if and node construction is going to get awful pretty fast. What common sub-expressions can we factor out?
singleton x = Node Leaf x Leaf
That makes life a little easier:
stree [] = Leaf
stree [x] = singleton x
stree ([x,y]) = if x < y then Node Leaf x (singleton y) else Node (singleton y) x Leaf
But it doesn't attack the basic problem of the nested if. One common trick for lists is to take them one element at a time. Can that work for us?
addToSTree :: Int -> STree -> STree
addToStree x Leaf = singleton x
addToStree x (Node left n right) | x < n = ...
| otherwise = ...
Can you fill in the dots above? Once you have that, then it'll be time to make a loop over the contents of the list.
BTree can be solved similarly.

Resources