未使用變
首先,明確標記變量爲未使用的是_
替換變量的方式。所以,你真的想:
treeFold (\_ ys -> 1 + sum ys)
,因爲你寫你有一個編譯器錯誤:
treeFold (\ys -> 1 + sum ys)
...這是不一樣的東西。
褶皺
其次,我會用手上的例子樹評估treeSize
所以你可以看到,有沒有神奇的事情:
treeSize (Tree 1 [Tree 2 [], Tree 3 []])
-- Inline definition of 'treeSize'
= treeFold (\_ ys -> 1 + sum ys) (Tree 1 [Tree 2 [], Tree 3 []])
-- Evaluate treeFold
= (\_ ys -> 1 + sum ys) 1 (map (treeFold (\_ ys -> 1 + sum ys)) [Tree 2 [], Tree 3 []])
-- Apply the anonymous function
= 1 + sum (map (treeFold (\_ ys -> 1 + sum ys)) [Tree 2 [], Tree 3 []])
-- Apply the 'map' function
= 1 + sum [ treeFold (\_ ys -> 1 + sum ys) (Tree 2 [])
, treeFold (\_ ys -> 1 + sum ys) (Tree 3 [])
]
-- Apply both 'treeFold' functions
= 1 + sum [ (\_ ys -> 1 + sum ys) 2 (map (treeFold (\_ ys -> 1 + sum ys)) [])
, (\_ ys -> 1 + sum ys) 3 (map (treeFold (\_ ys -> 1 + sum ys)) [])
]
-- Apply the anonymous functions
= 1 + sum [ 1 + sum (map (treeFold (\_ ys -> 1 + sum ys)) [])
, 1 + sum (map (treeFold (\_ ys -> 1 + sum ys)) [])
]
-- map f [] = []
= 1 + sum [ 1 + sum []
, 1 + sum []
]
-- sum [] = 0
= 1 + sum [1 + 0, 1 + 0]
= 1 + sum [1, 1]
-- Apply 'sum'
= 1 + 2
= 3
然而,有一個簡單的方法來記住如何treeFold
作品。它所做的就是用您提供的函數替換每個Tree
構造函數。
所以,如果您有:
Tree 1 [Tree 2 [Tree 3 [], Tree 4[]], Tree 5 [Tree 6 [], Tree 7 []]]
...你申請treeFold f
到,它會評估爲:
f 1 [f 2 [f 3 [], f 4 []], f 5 [f 6 [], f 7 []]]
treeSum
只是特殊情況下f = (\_ ys -> 1 + sum ys)
:
1 + sum [1 + sum [1 + sum [], 1 + sum []], 1 + sum [1 + sum [], 1 + sum []]]
= 7
Currying
最後一點是如何在Haskell中進行咖啡的工作。當你定義像函數:
foo x y = x + y
...的編譯器實際上是desugars兩個嵌套函數:
foo = \x -> (\y -> x + y)
這就是爲什麼你可以部分應用功能,在Haskell只是一個參數。當你寫foo 1
,將其轉換爲:
foo 1
= (\x -> (\y -> x + y)) 1
= \y -> 1 + y
換句話說,它返回一個參數的一個新功能。
在Haskell中,所有函數只需要一個參數,我們通過返回新函數來模擬多個參數的函數。這種技術被稱爲「咖喱」。
如果你喜歡更傳統的主流語言的多參數的方法,你可以通過讓函數接受一個元組參數模擬它:
f (x, y) = x + y
然而,這不是真正地道的Haskell,並贏得了」不會給你任何性能改善。
[爲什麼函數式編程很重要](http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf)。 – 2013-04-26 23:34:12