how to define zip function over trees in haskell - haskell

data Tree a = Leaf a | Node (Tree a ) (Tree a)
I can't figure out how to write a tree version of zip and zipWith functions in Haskell.

Your tree does not allow well formed empty trees - you can make a dodgy one Node undefined undefined but this is not very good. As others have commented a simpleminded treeZip will need both trees to have the same shape to get a "good" result.
zipTree :: Tree a -> Tree b -> Tree (a,b)
zipTree (Leaf a) (Leaf b) = Leaf (a,b)
ZipTree (Node l1 r1) (Node l2 r2) =
let l = zipTree l1 l2
r = zipTree r1 r2
in Node l r
-- Problems...
zipTree (Node _ _) (Leaf _) = Node undefined undefined
ZipTree (Leaf _) (Node _ _) = Node undefined undefined
Note that simpleminded tree zipping truncates on shape not just "length" (if shapes don't match it will truncate) - this is more severe than lists which truncate "on length" (strictly speaking lists do truncate on "shape" but the "shape" must always be the same).
For this reason if I was writing a Tree library I wouldn't define zipTree.

Related

Relationships in a Tree (Haskell)

Binary trees with values in the leaves and nodes are defined by:
data Tree a = Leaf a
| Node a (Tree a) (Tree a)
deriving (Eq, Show)
For example,
10
/ \
/ \
8 2
/ \ / \
3 5 2 0
exTree :: Tree Int
exTree = N 10 (N 8 (H 3) (H 5))
(N 2 (H 2) (H 0))
Well, I need a function called RelationshipBinaryTree, which generates a list of tuples, whose first component is an x and its second the father. In this tree,
relationshipBinaryTree :: Tree a -> [(a,a)]
relationshipBinaryTree exTree = [(10,8),(8,3),(8,5),(10,2),(2,2),(2,0)]
Also, I need to define it in the Data.Tree hackage (https://hackage.haskell.org/package/containers-0.5.11.0/docs/Data-Tree.html)
I hope you can help me because I don't understand trees and graphs very well.
I have tried this
relationshipBinaryTree :: Tree a -> [(a,a)]
relationshipBinaryTree (L _) = []
relationshipBinaryTree (N _ (Tree i) (Tree d)) = relationshipBinaryTree (N _) ++ relationshipBinaryTree (Tree i) ++ relationshipBinaryTree (Tree d)
You want to use Data.Tree, but Data.Tree isn't even about binary trees, but about multi way trees (a.k.a. rose trees). However, if you had a function value :: Tree a -> a, then of course you could map it to the children of a rose tree and combine the result with the value.
Now, there exists a function that does that in Data.Tree, it's called rootLabel. And there is another function to geht the children of a node, it's called subForest.
That comes from the definition of Tree in Data.Tree:
Node
rootLabel :: a -- label value
subForest :: Forest a -- zero or more child trees
So we could define for rose trees:
fatherChild :: Tree a -> [(a, a)]
fatherChild t = map mkPair children ++ concatMap fatherChild children
where mkPair child = (rootLabel t, child)
children = subForest t
Example:
fatherChild (Node 3 [Node 8 [], Node 4 []])
> [(3,8),(3,4)]
Your example:
fatherChild (Node 10 [Node 8 [Node 3 [], Node 5 []], Node 2 [Node 2 [], Node 0 []]])
> [(10,8),(10,2),(8,3),(8,5),(2,2),(2,0)]
Now, this doesn't answer your question about binary trees, but I would like to leave that to you as an exercise, because it will be very similar (except if you get stuck). (And please don't use rose trees as binary trees, because there is no type safety to ensure that there are always two children.)
A simple way to do it is by getting the value with an auxiliary function and then do the recursion:
data Tree a = Leaf a
| Node a (Tree a) (Tree a) deriving (Eq, Show)
exTree :: Tree Int
exTree = Node 10 t1 t2
t1 = Node 8 (Leaf 3) (Leaf 5)
t2 = Node 2 (Leaf 2) (Leaf 0)
relationshipBinaryTree :: Tree a -> [(a,a)]
relationshipBinaryTree (Leaf _) = []
relationshipBinaryTree (Node v i d) = [(v, getVal i), (v, getVal d)] ++ relationshipBinaryTree i ++ relationshipBinaryTree d
getVal (Node v _ _) = v
getVal (Leaf v) = v
relationshipBinaryTree exTree
=> [(10,8),(10,2),(8,3),(8,5),(2,2),(2,0)]

zipWith for trees in Haskell

I am learning Haskell using The Haskell School of Expression: Learning Functional Programming through Multimedia and I am unsure how to go about solving this exercise.
Using the definition of trees given by
data Tree a = Node (Tree a) (Tree a) | Leaf a
Define tree versions of the list functions zip and zipWith. There
will be cases at the leaves or where trees are of different shapes
where you’ll have to make design decisions. Try to make your decisions
as elegant as possible.
For zip I have this but I am unsure if it is "elegant"
zipTree :: Tree a -> Tree b -> Tree (a,b)
zipTree (Leaf a) (Leaf b) = Leaf (a,b)
zipTree (Node l1 r1) (Node l2 r2) =
let l = zipTree l1 l2
r = zipTree r1 r2
in Node l r
-- Problems...
zipTree (Node _ _) (Leaf _) = Node undefined undefined
zipTree (Leaf _) (Node _ _) = Node undefined undefined
And I am unsure how to adapt it to have zipWith functionality although I do know a elegant definition of zipWith.
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
zipWith _ _ _ = []
First of all I believe your solution is not elegant because you are using undefined.
You want to avoid partial functions, and structures, as much as possible and simply inserting some Node undefined undefined in a tree structure doesn't sound like a good idea.
Think about this: once you have a Node undefined undefined how would it act with the other operations on the tree? You'd probably get tons of exceptions.
So you have to find an alternative.
zipTree (Node l r) (Leaf a) = Node x y
where
x = ... ?
y = ... ?
Now how should x and y be defined? x should depend on l and Leaf a while y should depend on r and Leaf a.
The easiest way to define this case is to simply perform the recursive calls:
zipTree (Node l r) a#(Leaf _) = Node (zipTree l a) (zipTree r a)
So we are zipping all leafs in the l and r subtrees with the leaf a.
As for the zipWithTree: that's easy. You have to add an f parameter and use f x y instead of (x, y) when you perform the zipping, which is done only in the Leaf v Leaf case:
zipWithTree f (Leaf a) (Leaf b) = Leaf $ f a b
Obviously you have to add the f parameter to all the rules and pass f to recursive calls.
Note that there is also an other way to define zipWith, which is:
zipTree (Node _ _) (Leaf a) = Leaf (undefined, a)
This still isn't a good solution because it introduces an undefined however it has some advantages against the Node undefined undefined solution:
It acts for similarly to zip from lists. zip [1,2] [1,2,3,4] == [(1,1), (2,2)] so you stop when the shorter list ends.
The undefined is inside the value. This allows for example to have:
mapTree snd (zipTree x y) == y
whenever x has longer branches. Using Node undefined undefined you have mapTree f (zipTree x y) is always an exception whenever the trees aren't isomorphic (because mapTree will try to evaluate undefined).

Haskell: Defining Trees using zip/zipWith [duplicate]

I am learning Haskell using The Haskell School of Expression: Learning Functional Programming through Multimedia and I am unsure how to go about solving this exercise.
Using the definition of trees given by
data Tree a = Node (Tree a) (Tree a) | Leaf a
Define tree versions of the list functions zip and zipWith. There
will be cases at the leaves or where trees are of different shapes
where you’ll have to make design decisions. Try to make your decisions
as elegant as possible.
For zip I have this but I am unsure if it is "elegant"
zipTree :: Tree a -> Tree b -> Tree (a,b)
zipTree (Leaf a) (Leaf b) = Leaf (a,b)
zipTree (Node l1 r1) (Node l2 r2) =
let l = zipTree l1 l2
r = zipTree r1 r2
in Node l r
-- Problems...
zipTree (Node _ _) (Leaf _) = Node undefined undefined
zipTree (Leaf _) (Node _ _) = Node undefined undefined
And I am unsure how to adapt it to have zipWith functionality although I do know a elegant definition of zipWith.
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
zipWith _ _ _ = []
First of all I believe your solution is not elegant because you are using undefined.
You want to avoid partial functions, and structures, as much as possible and simply inserting some Node undefined undefined in a tree structure doesn't sound like a good idea.
Think about this: once you have a Node undefined undefined how would it act with the other operations on the tree? You'd probably get tons of exceptions.
So you have to find an alternative.
zipTree (Node l r) (Leaf a) = Node x y
where
x = ... ?
y = ... ?
Now how should x and y be defined? x should depend on l and Leaf a while y should depend on r and Leaf a.
The easiest way to define this case is to simply perform the recursive calls:
zipTree (Node l r) a#(Leaf _) = Node (zipTree l a) (zipTree r a)
So we are zipping all leafs in the l and r subtrees with the leaf a.
As for the zipWithTree: that's easy. You have to add an f parameter and use f x y instead of (x, y) when you perform the zipping, which is done only in the Leaf v Leaf case:
zipWithTree f (Leaf a) (Leaf b) = Leaf $ f a b
Obviously you have to add the f parameter to all the rules and pass f to recursive calls.
Note that there is also an other way to define zipWith, which is:
zipTree (Node _ _) (Leaf a) = Leaf (undefined, a)
This still isn't a good solution because it introduces an undefined however it has some advantages against the Node undefined undefined solution:
It acts for similarly to zip from lists. zip [1,2] [1,2,3,4] == [(1,1), (2,2)] so you stop when the shorter list ends.
The undefined is inside the value. This allows for example to have:
mapTree snd (zipTree x y) == y
whenever x has longer branches. Using Node undefined undefined you have mapTree f (zipTree x y) is always an exception whenever the trees aren't isomorphic (because mapTree will try to evaluate undefined).

Retrieve minimum from tree and the tree itself - haskell

With this function, i can remove the minimum in a binary search tree:
data BTree a = Empty
| Node a (BTree a) (BTree a)
semmin :: BTree a -> BTree a
semmin (Node x Empty Empty) = Empty
semmin (Node x l r) = Node x (semmin l) r
I want to retrieve the minimum value and the tree without this minimum, the trick is, i can traverse it only once.
The type is mimSmim :: BTree a -> (a,BTree a)
how should i do it?
EDIT:
Does this count as one traverse?
semmin :: BTree a -> (a,BTree a)
semmin (Node x Empty Empty) = (x,Empty)
semmin (Node x l r) = let i= (semmin l)
in (fst(i),(Node x (snd(i)) r))
Here's a hint: If you are at a Node x l r and you already knew that the left tree's mimSmim l was (a, l'), then the Node's mimSmim (Node x l r) would be (a, Node x l' r).
You are looking for a zipper. A [zipper][1] is a representation of another data structure that lets you focus one section of the entire structure without losing the rest. Please see the last chapter of Learn You A Haskell for an intuitive approach to developing the zipper data type and functions to use on it.
The posted code is on the right track, even if not completely correct:
semmin :: BTree a -> (a,BTree a)
semmin (Node x Empty Empty) = (x,Empty)
semmin (Node x l r) = let i= (semmin l)
in (fst(i),(Node x (snd(i)) r))
As a hint for improving your code, not that the following crashes:
semmin (Node 1 Empty (Node 2 Empty Empty))
Also, to improve readability a bit, I would suggest:
semmin :: BTree a -> (a,BTree a)
semmin (Node x Empty Empty) = (x,Empty)
semmin (Node x l r) = let (minValue, minTree) = semmin l
in (minValue, Node x minTree r)
Finally, this looks as if it's returning the whole tree back, instead of the tree at which the minimum is found. Check if that's the case, and if that's what you want.

Check if a tree is a Perfect Tree

I want to write a Haskell function that checks if a tree is a perfect tree. I know that a tree is perfect if all the leaves of the tree are at the same depth.
I know I would start off like this
perfectTree :: Tree a -> Bool
But seeing that my grasp on the actual definition isn't too strong, can anyone actually explain what a perfect tree is and how you would go about checking that a tree is perfect in Haskell
I should have included that I defined data Type as follows:
data Tree a = Leaf | Node a (Tree a) (Tree a)
One way is to define a helper function perfectTreeHeight :: Tree a -> Maybe Int that returns Just the height of the tree if it's perfect, or Nothing otherwise. This is much easier to implement since you actually get the heights from the recursive calls so you can compare them. (Hint: use do-notation)
perfectTree is then just a trivial wrapper around this function.
import Data.Maybe (isJust)
perfectTree :: Tree a -> Bool
perfectTree = isJust . perfectTreeHeight
perfectTreeHeight :: Tree a -> Maybe Int
perfectTreeHeight = ...
Have you tried to think recursively about this?
Solution: The subtrees of the tree must all be perfect trees. Also, the depths of those subtrees should be equal. End.
I hope this high level solution/idea helps. I avoided to give an actual definition of perfectTree because I lack the actual definition of a Tree.
I'm assuming that your tree looks something like this...
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving Show
Now, we could define a recursive height function along these lines:
height :: Tree a -> Maybe Int
height (Leaf _) = Just 1
height (Branch a b) = ???
Ind the second case (???), we want to add one to the height of the subtrees, but only if they are perfect, and only if they have the same height. Let's define a helper function, same, which takes the heights of the subtrees, and returns a Maybe Int containing their height, but only if they are both perfect and have the same height.
same :: Eq a => Maybe a -> Maybe a -> Maybe a
same (Just a) (Just b) = if a == b then Just a else Nothing
same _ _ = Nothing
Now we can finish the height function. All it needs to do is add 1 to the height of the subtrees.
height :: Tree a -> Maybe Int
height (Leaf _) = Just 1
height (Branch a b) = maybe Nothing (Just . (1+)) subTreeHeight
where subTreeHeight = same (height a) (height b)
And here's how to use it.
main :: IO ()
main = do
let aTree = (Leaf 'a')
print aTree
print $ height aTree
let bTree = Branch (Leaf 'a') (Leaf 'b')
print bTree
print $ height bTree
let cTree = Branch (Leaf 'a') (Branch (Leaf 'b') (Leaf 'c'))
print cTree
print $ height cTree
let dTree = Branch (Branch (Leaf 'a') (Leaf 'b')) (Branch (Leaf 'c') (Leaf 'd'))
print dTree
print $ height dTree
When I run this, I get:
Leaf 'a'
Just 1
Branch (Leaf 'a') (Leaf 'b')
Just 2
Branch (Leaf 'a') (Branch (Leaf 'b') (Leaf 'c'))
Nothing
Branch (Branch (Leaf 'a') (Leaf 'b')) (Branch (Leaf 'c') (Leaf 'd'))
Just 3

Resources