Haskell Tree to List - preorder traversal - haskell

Given the following tree structure in Haskell:
data Tree = Leaf Int | Node Int Tree Tree deriving Show
How can I get Haskell to return a list of the data in pre-order?
e.g. given a tree:
Node 1 (Leaf 2) (Leaf 3)
return something like:
preorder = [1,2,3]

You could aim to a more general solution and make your data type an instance of Foldable.
There is a very similar example at hackage, but that implements a post-order visit.
If you want to support pre-order visits you will have to write something like this:
import qualified Data.Foldable as F
data Tree a = Leaf a | Node a (Tree a) (Tree a) deriving Show
instance F.Foldable Tree where
foldr f z (Leaf x) = f x z
foldr f z (Node k l r) = f k (F.foldr f (F.foldr f z r) l)
With this, you'll be able to use every function that works on Foldable types, like elem, foldr, foldr, sum, minimum, maximum and such (see here for reference).
In particular, the list you are searching for can be obtain with toList. Here are some examples of what you could write by having that instance declaration:
*Main> let t = Node 1 (Node 2 (Leaf 3) (Leaf 4)) (Leaf 5)
*Main> F.toList t
[1,2,3,4,5]
*Main> F.foldl (\a x -> a ++ [x]) [] t
[1,2,3,4,5]
*Main> F.foldr (\x a -> a ++ [x]) [] t
[5,4,3,2,1]
*Main> F.sum t
15
*Main> F.elem 3 t
True
*Main> F.elem 12 t
False

Use pattern matching
preorder (Leaf n) = [n]
preorder (Node n a b) = n:(preorder a) ++ (preorder b)

Ok, sorry about the late reply, but I got this working as follows:
preorder(Leaf n) = [n]
preorder(Node n treeL treeR) = [n] ++ preorder treeL ++ preorder treeR'code'
This however does not work for me still
preorder (Leaf n) = [n]
preorder (Node n a b) = n:(preorder a) ++ (preorder b)

Related

Sumation of tree

So for this problem I tried to take the sum of all leaves in a tree. But it's shooting an error every time. I am providing a snippet of the code I wrote.
Sample case
t1 =NODE 1 (NODE 2 (NODE 3 (LEAF 4) (LEAF 5)) (LEAF 6)) (NODE 7 (LEAF 8) (LEAF 9))
Answer should be 32.
data Tree a = LEAF a | NODE a (Tree a) (Tree a) deriving (Show, Read, Eq)
tre (LEAF a) = a
tre (NODE a (Tree b) (Tree c)) = [Tree b, Tree c]
sum [] accum = []
sum list#(x:xs) accum = if tre x == Int
then sumTree xs (accum + x)
else sumTree x accum
sumTree :: Num p => Tree p -> p
sumTree p accum= let
list = tre p
in sum list accum
32
The Haskell snipet provided is not the idiomatic Haskell way of solving the problem.
You don't need the tre function => use Pattern matching on constructors of your type
You don't have to use tre x == Int let out the magic of type inference
I've provided the following snippet of the code, load it into ghci and use :i Tree and :i sumTree to understand the types
module Main where
data Tree a = Leaf a | Node a (Tree a) (Tree a) deriving (Show)
sumTree (Leaf a) = a
sumTree (Node a l r) = a + sumTree l + sumTree r
main = do
let tree = Node 5 (Node 21 (Leaf 14) (Leaf 13)) (Leaf 29)
putStrLn $ show tree
putStrLn $ show $ sumTree tree

Fingertree head complexity

I was just reading Apfelmus' excellent introduction to Finger Trees for the second time and started to wonder about his implementation of head:
import Prelude hiding (head)
data Tree v a = Leaf v a
| Branch v (Tree v a) (Tree v a)
toList :: Tree v a -> [a]
toList (Leaf _ a) = [a]
toList (Branch _ x y) = toList x ++ toList y
head :: Tree v a -> a
head (Leaf _ a) = a
head (Branch _ x _) = head x
As implementing functions in terms of one another is a quite nice way of reusing code, it got me thinking if the following implementation would be as efficient (complexity wise) as his original:
import Prelude -- not needed, just for making it obvious
data Tree v a = Leaf v a
| Branch v (Tree v a) (Tree v a) deriving Show
toList :: Tree v a -> [a]
toList (Leaf _ a) = [a]
toList (Branch _ x y) = toList x ++ toList y
head' :: Tree v a -> a
head' = head . toList
Is lazy evaluation as efficient as the original implementation?
Yes, head and head' should have the same time complexity if handed to GHC. I would expect a small constant-factor difference in favor of head (maybe 60% confident of this -- the list fusion optimization stuff is pretty wild when it works).

Haskell - Create a fold function for tree type

I have this simple data Tree :
data Tree = Leaf Int | Node [Tree]
And I have to devellop a fold function for this type :
foldTree :: (Int -> a) -> ([a] -> a) -> Tree -> a
for example :
foldTree (+1) sum (Node[ (Leaf 2), (Leaf 3)])
will return (2+1)+(3+1) = 7
For leafs, I have :
foldTree f g (Leaf n) = (f n)
But I have no ideas for develop the nodes's case.
I'm french, also sorry for the mistakes.
It sometimes helps to look at what is available in scope and their types. Here's a solution:
foldTree f g (Leaf n) = (f n)
foldTree f g (Node subtrees) =
let as = map (foldTree f g) subtrees -- as :: [a]
in g as

Can this implementation of in-order traversal of a binary tree be improved?

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"]

Depth of a tree (Haskell)

I'm trying to figure out how to calculate the depth of a general tree in Haskell. I can figure out the solution for simple binary trees, but not for general trees with any number of leaves.
Here's the code I have for binary trees.
--depth of a binary tree.
depth :: Tree a -> Int
depth Nil = 0
depth (Node n x1 x2) = 1 + max (depth x1) (depth x2)
How can I modify this for general trees? General trees contain a list of trees, and that is where I am encountering difficulty.
Secondly, I want to turn the tree into a list (so I can do operations such as calculating the sum, etc.)
Again, I can figure it out for binary trees but not for general trees.
--tree into a list.
treeToList:: Tree a -> [a]
treeToList Nil = []
treeToList (Node n x1 x2)
= collapse x1 ++ [n] ++ collapse x2
Use Foldable to get single values out, use Functor to map functions
user2407038's good answer shows you how to write a Foldable instance by hand, which is very good advice, and you can use foldMap not just to make treeToList, but also to make handy other functions.
GHC lets you derive these instances automatically:
{-# LANGUAGE DeriveFunctor, DeriveFoldable #-}
import Data.Monoid
import Data.Foldable
data Tree a = Node a [Tree a]
deriving (Show,Functor,Foldable)
Let's use an example to test this out:
example :: Tree Int
example = Node 3 [Node 2 [], Node 5 [Node 2 [],Node 1 []],Node 10 []]
-- 3
-- |
-- +--+-----+
-- 2 5 10
-- |
-- +--+
-- 2 1
Let's use fmap to multiply everything by 10:
> example
Node 3 [Node 2 [], Node 5 [Node 2 [], Node 1 []], Node 10 []]
> fmap (*10) example
Node 30 [Node 20 [],Node 50 [Node 60 [],Node 10 []],Node 100 []]
Use a Monoid to combine values
A Monoid lets you combine (mappend) values, and has a do-nothing/identity value called mempty.
Lists are a Monoid, with mempty = [] and mappend = (++), numbers are moinoids in more than one way, for example, using (+) (the Sum monoid), using (*) (the Product monoid), using maximum (I had to hand-write the Max monoid).
We'll use foldMap to tag the Ints with what monoid we want to use:
> foldMap Sum example
Sum {getSum = 23}
> foldMap Product example
Product {getProduct = 600}
> foldMap Max example
Max {unMax = 10}
You can define your own monoid however you like - here's how to make the Max monoid:
instance (Ord a,Bounded a) => Monoid (Max a) where
mempty = Max minBound
mappend (Max a) (Max b) = Max $ if a >= b then a else b
The most general fold you can make
In this great question with great answers, Haskell's top asker, MathematicalOrchid asks how to generalise fold to other data types. The answers to the question are great and worth reading.
A generalised fold simply replaces each constructor of the data type with a function and evaluates to get a value.
The hand-rolled way is to look at the types of each of the constructors, and make a function that takes a function argument to match each constructor and an argument for the object itself, and returns a value.
Examples:
[] has two constructors, (:) :: a -> [a] -> [a] and [] :: [a] so
foldList :: (a -> l -> l) -> l -> [a] -> l
foldList useCons useEmpty = f where
f (a:as) = useCons a (f as)
f [] = useEmpty
Either a b has two constructors, Left :: a -> Either a and Right :: a -> Either so
foldEither :: (a -> e) -> (b -> e) -> Either a b -> e
foldEither useLeft useRight = f where
f (Left a) = useLeft a
f (Right b) = useRight b
Generalised fold for your tree
generalFold :: (a -> [t] -> t) -> Tree a -> t
generalFold useNode = f where
f (Node a ts) = useNode a (map f ts)
we can use that to do pretty much anything we want to to a tree:
-- maximum of a list, or zero for an empty list:
maxOr0 [] = 0
maxOr0 xs = maximum xs
height :: Tree a -> Int
height = generalFold maxPlus1 where
maxPlus1 a as = 1 + maxOr0 as
sumTree = generalFold sumNode where
sumNode a as = a + sum as
productTree = generalFold productNode where
productNode a as = a * product as
longestPath = generalFold longest where
longest a as = a + maxOr0 as
Let's test them:
ghci> example
Node 3 [Node 2 [],Node 5 [Node 2 [],Node 1 []],Node 10 []]
ghci> height example
3
ghci> sumTree example -- 3 + sum[2, 5+sum[2,1], 10] = 3+2+5+2+1+10
23
ghci> productTree example -- 3*(2*(5*(2*1))*10) = 3*2*5*2*1*10
600
ghci> longestPath example -- 3 + maximum [2, 5+maximum[2,1], 10]
13
ghci> toList example -- 3 : concat [[2], 5:concat[[2],[1]], [10]]
[3,2,5,2,1,10]
Think about generalizing the pattern to lists:
data Tree a = Node a [Tree a] | Nil
depth Nil = 0
depth (Node _ [a]) = 1 + depth a
depth (Node _ [a,b]) = 1 + max (depth a) (depth b)
depth (Node _ [a,b,c]) = 1 + max (max (depth a) (depth b)) (depth c)
etc...
Well, all you are doing is finding the depth of each subtree (map depth), then finding the maximum of those numbers (maximum):
depth Nil = 0
depth (Node _ a) = 1 + maximum (map depth a)
You can flatten the tree in the same way, just map over the subtrees:
treeToList (Node n a) = n : concat (map treeToList a)
You have to use concat because map collapse returns a list of lists and you just want a list. Alternatively, you can define an instance for the Foldable typeclass and you automatically get toList :: Foldable t => t a -> [a]
import Data.Foldable
import Data.Monoid
instance Foldable Tree where
foldMap f Nil = mempty
foldMap f (Node a n) = f a `mappend` mconcat (map foldMap n)
If you scrutinize the definition of foldMap very carefully, you will see that it is just a more general treeToList, where : is replaced by mappend and [] by mempty. Then it is logical that you can write treeToList in terms of the monoid ([], ++):
data List a = List {getList :: [a]}
instance Monoid (List a) where
mempty = List []
mappend (List a) (List b) = List (a ++ b)
treeToList = getList . foldMap (List . (:[]))
A few pointers:
Take a look at the map function which allows you to apply a function to each element in a list. In your case you want to apply depth to each Tree a in the list of children.
After you get that part you have to find the max depth in the list. Do a google search for "haskell max of list" and you'll find what you need.

Resources