Reputation: 41
I am trying to reverse the children of a Tree in haskell. The Tree looks like this:
data Tree v e = Node v [(e,Tree v e)]
At the moment I do it with these two functions:
rev :: Tree v e -> Tree v e
rev (Node v []) = Node v []
rev (Node v xs) =
let xs' = (rev'(snd (unzip xs)))
in Node v (zip (fst (unzip xs)) (map rev xs'))
rev' :: [Tree v e] -> [Tree v e]
rev' [] = []
rev' (x:xs) = (rev' xs) ++ [x]
I am not even sure if this works 100%. Is there any way to do it recursive in just one function? I feel like my way is inefficient. I was trying to write a function that looks like this:
revRec :: Tree v e -> Tree v e
revRec (Node v []) = Node v []
revRec (Node v (x:xs)) = Node v (revRec xs ++ [x])
Obviosuly I can't call revRec
with xs
since xs
a list. I just can't wrap my head around this problem even though I feel like it shoudn't be that hard.
Upvotes: 0
Views: 1278
Reputation: 120711
Zeroth, clean up your code. You don't need those many parens, and you should avoid duplicate computations. fst
and snd
on twice the same thing? Meh. Better use pattern matching:
rev :: Tree v e -> Tree v e
rev (Node v xs)
= let (es, cs) = unzip xs
xs' = rev' cs
in Node v $ zip es (map rev xs')
rev' :: [Tree v e] -> [Tree v e]
rev' [] = []
rev' (x:xs) = rev' xs ++ [x]
First note that rev'
is not specific to lists of trees, at all! It's just an inefficient implementation of the standard reverse
function, which works on any list.
Second, this unzipping/zipping is a bit clumsy. Are you sure this is actually the behaviour you want: right now you're only reversing the list of children, but the order of elements stays the same. If not, then you'd better do it all with one reverse and one map:
rev :: Tree v e -> Tree v e
rev (Node v xs) = Node v . reverse $ map (\(e,c) -> (e, rev c)) xs
or, even nicer,
import Control.Arrow
rev (Node v xs) = Node v . reverse $ map (second rev) xs
Upvotes: 2