星期六, 10月 04, 2008

Haskell Learning Note(3)

試論curring

在Haskell中,不用C++這麼複雜的方法來解決問題,而是採用curried function來解決這個問題。

Prelude> let add x y = x + y   -- 簡單來說就是寫一個 (+)
Prelude> :t add
add :: (Num a) => a -> a -> a -- 此時的add是一個具有兩個引數的function
Prelude> :t add 1
add 1 :: (Num t) => t -> t -- 此時的add 1 是具有一個引數的function
Prelude> :t add 1 2
add 1 2 :: (Num t) => t -- 此時的add 1 2是一個不具有引數的function

在Haskell裡,使用單純的curried function即可解決,寫起來很像C++的function default arguemnt,意義不太一樣,在Haskell裡是真的把引數代入形成一個新的function,其實+ operator也可以做出同樣的功能(Josh Ko說這是語法糖XD)

Prelude> :t (+)
(+) :: (Num a) => a -> a -> a
Prelude> :t (1+)
(1+) :: (Num t) => t -> t
Prelude> :t (1+2)
(1+2) :: (Num t) => t

寫到這裡我在想,我幹麻沒事自己寫一個add呢 XD那麼,可以試著用map寫出一點有趣的東西

Prelude> map (1+) [1..10]
[2,3,4,5,6,7,8,9,10,11]

當然,一個curried function在FP中的功用不止於此,curried funciton可以做更多事,隨你寫,隨你造,而不用C++ STL裡的bind2nd這種相較之下較不直覺的方法。curried fuction的好處是在Haskell底下是lazy evaluation,也就是說,你function引數可以不用給全,直到你要求把答案算出來的那一刻把argument給全就行了,而且可以隨你組合,隨你寫,可以做出相當多的靈活變化,也就是說,curried function並非要求一次把function arguement給齊,在Haskell底下大部分的funciton都是curried function。

那麼有沒有要求要一次給齊的,換個腦子想想,就是uncurried function,在這樣子的一個function底下,沒有一次給足所有的argument就會出錯(一時想不到有什麼function)

補充:當我們寫(1+)而我們又呼叫這個function時,是類似C++的default argument還是wrapper function的技法呢,如果記得是沒有錯,是前者,也就是說,不管怎麼compose,都是只有一層的呼叫,相當的方便。


---
真糟,寫的真少。

張貼留言