【发布时间】:2016-07-05 17:46:24
【问题描述】:
我正在尝试在 haskell 中反转 Tree 的孩子。树看起来像这样:
data Tree v e = Node v [(e,Tree v e)]
目前我使用这两个功能:
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]
我什至不确定这是否 100% 有效。有没有办法只在一个函数中递归?我觉得我的方式效率低下。我试图编写一个如下所示的函数:
revRec :: Tree v e -> Tree v e
revRec (Node v []) = Node v []
revRec (Node v (x:xs)) = Node v (revRec xs ++ [x])
显然我不能用xs 调用revRec,因为xs 是一个列表。即使我觉得它不应该那么难,我也无法解决这个问题。
【问题讨论】:
-
首先,你甚至不需要
rev (Node v []) = ..case,一般的list case也包括空的list case。其次,使用unzip似乎是完全合理的——应该消除使用fst和snd(也多次调用unzip)。您可以使用原始递归编写它,例如。rev (Node a ts) = Node a $ uncurry (\x y -> zip x (y [])) $ foldr (\(e,t) (as, bs) -> (e:as, bs . (rev t :))) ([], id) ts。但我真的怀疑这比unzip/reverse版本更有效(而且肯定更丑)。