好吧,讓我們來看看爲curried functionfoldr
類型簽名:
>:t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
所以foldr
取一個二元函數(即a->b->b
),一個b
值,a
值的列表,並返回一個值爲b
。
讓我們也看看documentation爲foldr
以獲得更明確的定義:
foldr相似,適用於二元運算,初始值(操作者通常是 右身份),以及列表中,降低了使用 二元運算符的列表中,由右至左:
現在,讓我們來看看類型簽名myConcat xs = foldr (++) []
> :t myConcat
myConcat :: t -> [[a]] -> [a]
嗯......這不是我們想要的...
的問題是,你永遠不提供foldr
[a]
類型的值。所以,現在,myConcat
需要一定的價值,任何類型,以滿足xs
和[a]
類型的值來完成foldr (++) []
,如:
> myConcat 2 [[1,2],[3,4]]
[1,2,3,4]
> myConcat Nothing [[1,2],[3,4]]
[1,2,3,4]
這樣的作品,但第一個參數是太浪費了。
然而,如果我們傳遞xs
值到foldr (++) []
,如:
myConcat xs = foldr (++) [] xs
,並檢查它的類型簽名
> :t myConcat
myConcat :: [[a]] -> [a]
嗯,好多了。現在myConcat使用xs
來完成foldr
函數。
另外,myConcat = foldr (++) []
也有效,實際上是point-free style programming的一個例子。如果我們檢查既然我們已經通過partial application提供foldr
它的前兩個參數的foldr (++) []
類型簽名,
> :t foldr (++) []
foldr (++) [] :: [[a]] -> [a]
,我們得到了一個功能回到那個意志需要[[a]]
值,做我們想要的!所以我們只是將它分配給一個名稱,它的工作方式就像上面的例子,但我們不需要明確地傳遞參數!
> let myConcat = foldr (++) []
> :t myConcat
myConcat :: [[a]] -> [a]
> myConcat [[1,2],[3,4]]
[1,2,3,4]
+1:一個非常容易理解的解釋;你碰巧有一個Haskell相關的博客嗎?我喜歡你的風格。 :-) –
@Frerich Raabe:謝謝!事實上,我有一個博客,主要是關於Scala,不過現在又是Haskell,但不幸的是它是德文的:http://dgronau.wordpress。com/ – Landei
非常感謝你,我現在明白了:)很好的解釋 – Adi