这很棘手。如果有任何孩子产生匹配,您希望该过程将节点的孩子短路。这是我的解决方案。
import Data.Maybe
ntreeReplace :: String -> String -> Tree -> Maybe Tree
ntreeReplace x y (Node z lis)
| (x==z) = Just (Node y lis)
| otherwise =
let (nothings, justs) = span (isNothing . ntreeReplace x y) lis
in case justs of
[] -> Nothing
(t:ts) -> Just (Node z (nothings ++ [fromJust $ ntreeReplace x y t] ++ ts))
ntreeReplace x y (Leaf z)
| (x==z) = Just (Leaf y)
| otherwise = Nothing
nTreeReplace
回报Nothing
如果有此树(即,我们应该重新使用输入不变)和Just t
不匹配,如果进行了替换(即我们应该t
更换输入)。我使用span
将儿童列表分成Nothing
s的前缀和第一个元素匹配的(可能为空)后缀。
该实现的,因为它在一个匹配的孩子叫ntreeReplace
两次,可能小的低效率:一次在span
谓词,并再次在构建替换节点。
我也推荐一个更高级别的功能replace
,它给你一个(可能相同的)Tree
,而不是Maybe Tree
。
replace :: String -> String -> Tree -> Tree
replace x y t =
case ntreeReplace x y t of
Nothing -> t
(Just t') -> t'
[编辑]随着@codebliss'建议的线,你可以改变data
声明
data Tree a = Empty | Leaf a | Node a [Tree a]
,你就必须改变唯一的其他东西是ntreeReplace
和replace
签名:
replace :: Eq a => a -> a -> Tree a -> Tree a
ntreeReplace :: Eq a => a -> a -> Tree a -> Maybe (Tree a)
我建议你按如下方式为树构造函数。这使得它更通用的,因此更多的功能编程的精神=) 数据树一空= |叶a |节点[树一] 获得(...) 而你需要做的,基本上是一棵树的地图。 – codebliss 2009-11-08 19:32:13