2011-02-04 33 views
0

運行摺疊(+)0示例給我一個關於(+)應用於太多參數的錯誤。爲什麼?BST摺疊函數的通用版本中的參數太多

data(Ord a, Show a, Read a) => BST a = Void | Node { 
    val :: a, 
    left, right :: BST a 
} deriving (Eq, Ord, Read, Show) 

sample = Node 5 (Node 3 Void Void) (Node 10 Void Void) 

fold :: (Read a, Show a, Ord a) => (a -> b -> b -> b) -> b -> BST a -> b 
fold _ z Void   = z 
fold f z (Node x l r) = f x (fold f z l) (fold f z r) 
Occurs check: cannot construct the infinite type: a = a -> a 
Probable cause: `+' is applied to too many arguments 
In the first argument of `fold'', namely `(+)' 
In the expression: fold' (+) 0 sample 

參見:fold

+0

你可能想看看讓你的類型的實例[可摺疊](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Foldable.html#t:Foldable)和[Traversable](http://hackage.haskell.org/packages /archive/base/latest/doc/html/Data-Traversable.html#t:Traversable) – 2011-02-04 03:18:04

回答

1

fold需要作爲第一個參數a -> b -> b -> b類型的功能,這是一個函數,有三個參數。另一方面,(+)只有兩個參數。

如果fold應該改變,或者如果你需要用不同的函數調用它,取決於你正在嘗試做什麼。

+0

ok,`fold(\ xyz - > x + y + z)0 sample`工作並彙總BST的所有元素。然而,儘管Haskell中定義的foldr和foldl很容易理解,但我無法想象BST fold函數實際上是如何應用於樹元素的。我的意思是順序,就像第一篇文章中的Haskell wiki鏈接一樣。 – gremo 2011-02-04 00:36:45

1

你的問題是你正在將函數應用到3個參數。類型簽名中的第一個參數說明了這一切。

fold :: (a -> b -> b -> b) -> b -> BST a -> b 
fold f z (Node x l r) = f x (fold f z l) (fold f z r) 

(+)只需要兩個參數,但是當你通過它,它試圖評估這個:

(+) x (fold (+) z l) (fold (+) z r) -- 3 arguments! =P 

你可能想用一個二元函數(折一個 - > A - > a)。假設你想使用(+)。你想要得到的結果是這樣的:

fold f z (Node x l r) = x + (fold f z l) + (fold f z r) 

從那裏可以很容易地概括:只是更換+的infixed f

fold f z (Node x l r) :: (a -> a -> a) -> a -> BST a -> a 
fold f z (Node x l r) = x `f` (fold f z l) `f` (fold f z r)