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
Related
I really like the repmin problem:
Write down repmin :: Tree Int -> Tree Int, which replaces all the numbers in the tree by their minimum in a single pass.
If I were writing something like this in python, I would go for passing values by their reference (let's say one-element lists instead of numbers is good enough):
def repmin(tree, wrapped_min_link=None):
x, subforest = tree
if wrapped_min_link is None:
wrapped_min_link = [x]
else:
[m] = wrapped_min_link
wrapped_min_link = [min(m, x)]
n = len(subforest)
subforest_min = [None] * n
for i in range(n):
if subforest[i]:
subforest_min[i] = repmin(subforest[i], wrapped_min_link)
return (wrapped_min_link, subforest_min)
It seems to me like a fitting way to wrap one's head around the knot-tying solution in Haskell (I wrote this one for rose trees from Data.Tree):
copyRose :: Tree Int -> Int -> (Tree Int, Int)
copyRose (Node x []) m = (Node m [], x)
copyRose (Node x fo) m =
let
unzipIdMinimum =
foldr (\ ~(a, b) ~(as, bmin) -> (a:as, b `min` bmin)) ([], maxBound :: Int)
(fo', y) = unzipIdMinimum . map (flip copyRose m) $ fo
in (Node m fo', x `min` y)
repmin :: Tree Int -> Tree Int
repmin = (loop . uncurry) copyRose
Yet, I reckon the solutions to work very differently. Here is my understanding of the latter one:
Let us rewrite loop for (->) a bit:
loop f b = let cd = f (b, snd cd) in fst cd
I reckon it to be loop for (->)'s workalike as snd gives the same degree of laziness as pattern-matching within let.
So, when repmin traverses through the tree, it is:
Building up the minimum in the tree to be returned as the second element of the pair.
Leaves snd $ copyRose (tree, m) behind in every node.
Thus, when the traversal comes to an end, the programme knows the value of snd $ copyRose (tree, m) (that is, the minimum in the tree) and is able to show it whenever some node of the tree is being computed.
Do I understand repmin in Haskell correctly?
This is more an extended comment than an answer, but I don't really think of your implementation as single-pass. It looks like it traverses the tree once, producing a new, lazily-generated, tree and the global minimum, but it actually produces a lazily generated tree and an enormous tree of thunks that will eventually calculate the minimum. To avoid this, you can get closer to the Python code by generating the tree eagerly, keeping track of the minimum as you go.
You'll note that I've generalized the type from Int to an arbitrary Ord type. You'll also note that I've used to different type variables to refer to the type of elements in the given tree and the type of the minimum passed in to generate a new tree—this lets the type system tell me if I mix them up.
repmin :: Tree a -> Tree a
repmin = (loop . uncurry) copyRose
copyRose :: Ord a => Tree a -> b -> (Tree b, a)
copyRose (Node x ts) final_min
| (ts', m) <- copyForest x ts final_min
= (Node final_min ts', m)
copyForest :: Ord a => a -> [Tree a] -> b -> ([Tree b], a)
copyForest !m [] _final_min = ([], m)
copyForest !m (t : ts) final_min
| (t', m') <- copyTree m t final_min
, (ts', m'') <- copyForest m' ts final_min
= (t' : ts', m'')
copyTree :: Ord a => a -> Tree a -> b -> (Tree b, a)
copyTree !m (Node x ts) final_min
| (ts', m') <- copyForest (min m x) ts final_min
= (Node final_min ts', m')
Exercise: rewrite this in monadic style using ReaderT to pass the global minimum and State to keep track of the minimum so far.
When I take a mixed tree from char and float I have to seperate them as a Float or Character in haskell and add them to the specific list I tried to write something as you can see below;
I tried to take a as [a] in the else part but it gives error too.
data BETree = Leaf Float | Node Char BETree BETree deriving (Show, Ord, Eq)
charList :: [Char]
charList = []
floatList :: [Float]
floatList = []
toList :: BETree -> ([Float], [Char])
toList (Node a l r) = if (a :: Char ) then (charList ++ [a])
else (floatList ++ a)
I expect to entered values to seperate for floatList and charList however I get errors like this;
Couldn't match expected type ‘[[Char]]’ with actual type ‘Char’
OR
vice versa
There are a couple of aspects of Haskell that you haven't mastered yet, and they're causing you some difficulty.
First, as you probably know, Haskell takes its types very seriously. It's a strongly typed language, so that means that the whole concept of searching through a data structure to find values of a particular type is the wrong way of thinking about this problem. The definition of BETree is:
data BETree = Leaf Float | Node Char BETree BETree deriving (Show, Ord, Eq)
which says that this structure consists of Leafs that contain a Float and internal Nodes that contain a Char. So, if you want to find all the Char values, you don't check the types, you just look for the Nodes. They will all contain Chars and can't contain anything else, by the definition of BETree. In other words, in your function definition:
toList (Node a l r) = ...
you don't need to try to check the type of a -- it's guaranteed to be Char by the definition of Node in the BETree definition. If you separately write a definition:
toList (Leaf x) = ...
then you're similarly guaranteed that x is a Float, and you don't need to check any types.
Second, Haskell normally works with immutable values. This means that, unlike in most other languages, you usually don't start by creating an empty list and then trying to add elements to it in a separate function. Instead, you usually write recursive functions that return the "list so far", which they generate by adding an element (or elements) to the list returned by recursively calling themselves. As a simple example, to write a function that builds up the list of all positive integers in an input list, you'd write:
positiveInts :: [Int] -> [Int]
positiveInts (x:xs) | x > 0 = x : positiveInts xs -- add "x" to list from recursive call
| otherwise = positiveInts xs -- drop "x"
positiveInts [] = []
So. here's how it might work for your problem, starting with the simpler problem of just building the floatList:
toFloatList :: BETree -> [Float]
toFloatList (Leaf x) = [x] -- x is guaranteed to be a Float, so return it
toFloatList (Node _a l r) = -- _a can't be a float, so ignore it
toFloatList l ++ toFloatList r -- but recurse to find more Floats in Leafs
And test it:
> toFloatList (Node 'x' (Leaf 1.0) (Node 'y' (Leaf 3.0) (Leaf 4.0)))
[1.0,3.0,4.0]
>
Building just the charList is only slightly more complicated:
toCharList :: BETree -> [Char]
toCharList (Leaf _x) = [] -- x is guaranteed to be a Float, so no Chars here
toCharList (Node a l r) = -- "a" is a Char
toCharList l ++ [a] ++ toCharList r -- recurse and put "a" in the middle
and testing it:
> toCharList (Node 'x' (Leaf 1.0) (Node 'y' (Leaf 3.0) (Leaf 4.0)))
"xy"
> "xy" == ['x','y']
True
>
In Haskell, the list of Chars ['x','y'] is equivalent to the string "xy" which is why it gets printed this way.
Now, the easiest way to define toList is:
toList :: BETree -> ([Float], [Char])
toList bet = (toFloatList bet, toCharList bet)
This traverses the tree twice. If you want to build both lists together in a single traversal, things get significantly more complicated:
toList' :: BETree -> ([Float], [Char])
toList' (Leaf x) = ([x],[]) -- easy, since Leaf contains only one Float
toList' (Node a l r) = -- Nodes are harder
let (fl1, cl1) = toList' l -- lists from the left branch
(fl2, cl2) = toList' r -- lists from the right branch
in (fl1 ++ fl2, cl1 ++ [a] ++ cl2) -- combine with our Char "a"
and the test:
> toList (Node 'x' (Leaf 1.0) (Node 'y' (Leaf 3.0) (Leaf 4.0)))
([1.0,3.0,4.0],"xy")
> toList' (Node 'x' (Leaf 1.0) (Node 'y' (Leaf 3.0) (Leaf 4.0)))
([1.0,3.0,4.0],"xy")
>
This question already has an answer here:
Can this implementation of in-order traversal of a binary tree be improved?
(1 answer)
Closed 6 years ago.
data Tree a = Node a (Tree a) (Tree a) | Empty
toList :: (Tree a) -> [a]
toList (Node v l r ) = (toList l) ++ [v] ++ (toList r)
toList Empty = []
As we know it is not optimal because every ++ is connected with O(n) operations for concatenation of lists. The alternative solution is to use : instead of ++. But it causes error because of the fact toList Empty = []. So how to make optimal my solution?
You can't do it directly, since : only prepends a single element to a list. But in both child-branches you'll usually give multiple elements. The slow recursive implementation is needed to get around precisely this!
So, the way to go is to use a container with a more efficient concatenation operation! Such are available in libraries, e.g. sequence. But there is one container type that you can very quickly brew up yourself:
newtype DList a = DList { getDList :: [a] -> [a] }
instance Monoid (DList a) where
mempty = DList id
mappend (DList l1) (DList l2) = DList $ l1 . l2
singletonD :: a -> DList a
singletonD x = DList (x:)
With this, you can do
toDList :: Tree a -> DList a
toDList (Node v l r) = toDList l <> singletonD v <> toDList r
toDList Empty = mempty
This is an exact translation of your definition, but it won't have the same performance problem as when you concatenate ordinary lists.
Because these difference lists are so easy to implement, it's quite common in Haskell to just do it inline without further mention:
toList :: (Tree a) -> [a]
toList t = tdl t []
where tdl (Node v l r) = toList l . (v:) . tdl r
tdl Empty = id
You need to put things together differently to accomplish your goal. You can't just replace ++ with :. Try this:
toList t = toListPlus t []
toListPlus :: Tree a -> [a] -> [a]
toListPlus t xs should produce toList t ++ xs, but implemented with recursive calls to toListPlus, not using ++ or toList. Let's work through it. The base case is easy:
toListPlus Empty xs = xs
The recursive case isn't too bad either. We want to convert the left subtree to a list, sticking other stuff on after:
toListPlus (Node v l r) xs =
toListPlus l ???
What comes after? The root, and then the result of converting the right subtree, and then whatever gets tacked on:
toListPlus (Node v l r) xs =
toListPlus l (v : toListPlus r xs)
This function uses an implicit stack to keep track of the remaining work. This is probably the most efficient way to do it. If you wanted, you could use a zipper-style representation to make the stack explicit.
How does this solution relate to the one leftaroundabout described? Well, they're actually the same. We can see that by shifting the list argument over:
toListPlus Empty = \xs -> xs
toListPlus (Node v l r)
= \xs -> toListPlus l (v : toListPlus r xs)
= toListPlus l . (v :) . toListPlus r
I wrote a straightforward in-order-traversal function (toList1) for a binary tree. However, I worry about its complexity (memory / time). Is there a better way to implement it?
data Tree a = Empty | Node a (Tree a) (Tree a)
toList1 :: (Tree a) -> [a]
toList1 Empty = []
toList1 (Node x lx rx) = (toList lx) ++ [x] ++ (toList rx)
Haskell's append ++ performs linearly in the length of its left argument, which means that you may get quadratic performance if the tree leans left.
One possibility would be to use difference list.
Another one would be to define a Foldable instance:
data Tree a = Empty | Node a (Tree a) (Tree a)
instance Foldable Tree where
foldr f z Empty = z
foldr f z (Node a l r) = foldr f (f a (foldr f z r)) l
then, in-order-traversal comes out naturally:
toList :: Tree a -> [a]
toList = foldr (:) []
and
\> let tr = Node "root" (Node "left" Empty Empty) (Node "right" Empty Empty)
\> toList tr
["left","root","right"]
I have a structure for a tree and I want to print the tree by levels.
data Tree a = Nd a [Tree a] deriving Show
type Nd = String
tree = Nd "a" [Nd "b" [Nd "c" [],
Nd "g" [Nd "h" [],
Nd "i" [],
Nd "j" [],
Nd "k" []]],
Nd "d" [Nd "f" []],
Nd "e" [Nd "l" [Nd "n" [Nd "o" []]],
Nd "m" []]]
preorder (Nd x ts) = x : concatMap preorder ts
postorder (Nd x ts) = (concatMap postorder ts) ++ [x]
But how to do it by levels? "levels tree" should print ["a", "bde", "cgflm", "hijkn", "o"].
I think that "iterate" would be suitable function for the purpose, but I cannot come up with a solution how to use it. Would you help me, please?
You just need to compute the levels for all of the subtrees and zip them all together after the root:
levels :: Tree [a] -> [[a]]
levels (Nd a bs) = a : foldr (zipWith' (++)) [] (map levels bs)
Sadly, zipWith doesn't do the right thing, so we can instead use:
zipWith' f xs [] = xs
zipWith' f [] xs = xs
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
Update: there is some concern (which I agree with) that what you originally asked is a little weird as it's not a generic breadth-first tree to list convertor. What you probably really want is to concat the result of:
levels' (Nd a bs) = [a] : foldr (zipWith' (++)) [] (map levels' bs)
I'm guessing this is homework. On the assumption that it is, then here's some ideas for how to think about the problem that might lead you to an answer:
In preorder, first the current item is "reported", then recurse for all this node's tails. In postorder these two steps are done in reverse. In both cases, the recursion is "local", in the sense that it only need deal with one node at a time. Is this true for levelorder? Or to ask it another way, when levelorder recurses, do the results of the recursions interact or no? If so, then, what is the "unit" of recursion, if not a single Tree?
Understanding the nature of the recursion (or iteration..?) of levelorder will lead you to a solution that very simple and elegant. My version is only three lines long!
By the way, it might be nice to have these utility functions to make the code even clearer in some places:
element :: Tree a -> a
element (Nd x _) = x
subtrees :: Tree a -> [Tree a]
subtrees (Nd _ s) = s
Or, if you are familiar with record syntax in Haskell, you can achieve exactly this by changing your original Tree definition to:
data Tree a = Nd { element :: a, subtrees :: [Tree a] }
deriving Show
A full solution:
The key is realizing that levelorder requires recursion on a list of Tree. At each step the elements from each Tree is extracted, and the next step is upon the concatenation of the subtrees:
levelorder :: Tree a -> [a]
levelorder t = step [t]
where step [] = []
step ts = map element ts ++ step (concatMap subtrees ts)
This produces the elements in a single, flattened list, much like preorder and postorder do, and is the usual definition of a breadth-first traversal.
If instead you really want the elements grouped by level, a single change of the ++ operator to : will yield that version:
bylevel :: Tree a -> [[a]]
bylevel t = step [t]
where step [] = []
step ts = map element ts : step (concatMap subtrees ts)
Note: I have given type signatures for all top-level functions. This is a really good habit to get into, and will save you considerable time debugging.
Here is another version which can be applied to Tree a instead of Tree [a].
levelorder :: Tree a -> [[a]]
levelorder (Nd x ts) = [x]:(ziplist (map levelorder ts))
ziplist :: [[[a]]] -> [[a]]
ziplist l = if null ls then [] else (concat heads):(ziplist tails)
where
ls = filter (not.null) l
heads = map head ls
tails = map tail ls
If you want to concatenate the strings at the end you may use:
levelorder2 :: Tree [a] -> [[a]]
levelorder2 = (map concat).levelorder
levels :: (Tree a) -> [[a]]
levels (Nd x ts) = [[x]] ++ levelshelper ts
level2 = (map concat).levels
levelshelper :: [Tree a] -> [[a]]
levelshelper [] = []
levelshelper xs = (map (\(Nd x ts) -> x) xs) : (levelshelper (extractl xs))
--get the next level's Nd's
extractl :: [Tree a] -> [Tree a]
extractl [] = []
extractl ((Nd x ts):xs) = ts ++ (extractl xs)
My approach turned out being a bit more ham-handed than I wanted. Correct me if I'm wrong, though, since strings are lists of characters, but you're using polymorphic types, is it really so straightforward to to print your results out like specified in the problem? This code produces lists of lists of strings. ***Props to Chris in his more elegant answer for reminding me about the use of concat!!
You can repeat [] for empty list so that you don't get the problem with zipWith
levels :: Tree a -> [[a]]
levels Empty = repeat []
levels (Branch x l r) = [x] : zipWith (++) (levels l) (levels r)