问题描述
这是一棵二叉树,我正在尝试计算叶子的总和
-1
/ \
-5 10
/ \
-4 30
/ \
13 17
给出了数据声明。
data Tree = TNode Int [ Tree ] | TLeaf Int
这是我的代码
let t = TNode (-1) [TNode (-5) [ TNode (-4) [ Tleaf 13,Tleaf 17],Tleaf 30 ],Tleaf 10 ]
sumLeaves (Tleaf x)= x
sumLeaves (TNode x [tree])= sum[sumLeaves tree]
当我运行程序sumLeaves t时,表明函数sumLeaves中存在非穷尽模式。我认为问题是当有两个叶子的节点时,程序无法计数,但是我不这样做不知道如何解决。非常感谢您的帮助。
编辑: 测试1:
sumLeaves1 (Tleaf x)= [x]
sumLeaves1 (TNode x [Tleaf y])=[y]
sumLeaves1 (TNode x (y:ys))= sum ( (sumLeaves1 y) ++ (sumLeaves1 (TNode x ys)) )
测试2:
sumLeaves (Tleaf x)= x
sumLeaves (TNode x [Tleaf y])=y
sumLeaves (TNode x (y:ys))= (sumLeaves y) + sumLeaves (TNode x ys)
测试2正常工作,但是测试1给出了错误,当我删除sum()时,它给出了一个列表[13,17,30,10],这是正确的列表,但是> sum([13,10])在程序中工作。我该如何克服?
解决方法
您的(Tnode x [tree])
仅在节点具有个完全一棵子树时匹配。您应该匹配sublistlist的任何值,所以:
sumLeaves :: Tree -> Int
sumLeaves (Tleaf x) = x
sumLeaves (TNode x trees) = sum (…)
此处…
应该创建该节点的子代之和的列表。因此,您应该为trees
中的每个元素进行映射。我将其保留为练习。您可能想看看map :: (a -> b) -> [a] -> [b]
。
话虽如此,您不必自己对元素进行求和。您可以提升Tree
数据类型并利用DeriveFoldable
extension让Haskell为您派生一个Foldable
实例:
{-# LANGUAGE DeriveFoldable #-}
data Tree a = TNode a [ Tree a ] | TLeaf a deriving Foldable
sum :: (Foldable f,Num a) => f a -> a
是在任何Foldable
上定义的,因此我们可以求和:
Prelude> sum (TNode (-1) [TNode (-5) [ TNode (-4) [ TLeaf 13,TLeaf 17],TLeaf 30 ],TLeaf 10 ])
60