這很棘手。如果有任何孩子產生匹配,您希望該過程將節點的孩子短路。這是我的解決方案。
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