2017-04-18 80 views
1

sumListV3如何運作? myFoldr需要3個參數:函數,基數大小寫和列表。然而它以某種方式知道列表(基於你的輸入),即使它在內部代碼中從未被指定過。鬼怪haskell功能,不知何故知道你的輸入

我認爲sumListV2是最簡單的。 sumListV3如何編譯,更不用說功能正常?

myFoldr :: (a -> b -> b) -> b -> [a] -> b 
myFoldr _ baseCase [] = baseCase 
myFoldr f b (x:xs) = f x (myFoldr f b xs) 

sumListV2 :: [Int] -> Int 
sumListV2 xs = myFoldr (+) 0 xs 

sumListV3 :: [Int] -> Int 
sumListV3 = myFoldr (+) 0 
+1

它減少了eta。注意各種奇妙的用法,例如'plus =(+)' - 它如何知道有兩個參數?減少埃塔(可以googleable的術語)。 'sumListV4 = sum'與您的例子和相同的概念更相似。 –

+0

也許你不會因爲'foo xs = myFoldr(+)0 xs'而購買,那麼我們也知道'foo = myFoldr(+)0'。但是,你是否購買了其他含義?如果'foo = myFoldr(+)0'然後'foo xs = myFoldr(+)0 xs'是否有意義? –

回答

8

Haskell中的函數是「curried」的。

這意味着,當你有一個函數f :: a -> b -> c,它是真正a -> (b -> c)f a b真是(f a) b(因爲關聯規則)。

所以當你運行f a b時,它首先會做f a,它返回一個新的函數b -> c。然後,您可以給它一個b並得到您的最終答案c

這使您可以申請部分功能:

ghci> let add :: Int -> Int -> Int ; add a b = a + b 
ghci> add 2 3 
5 
ghci> (add 2) 3 
5 
ghci> let addToTwo = add 2 
ghci> :t addToTwo 
addToTwo :: Int -> Int 
ghci> addToTwo 6 
8 
ghci> addToTwo 9 
11 

什麼你對sumListV3例如正在做的是部分應用myFoldr。 (類型此處指定到你的情況。)

myFoldr  :: (Int -> Int -> Int) -> Int -> [Int] -> Int 
myFoldr  :: (Int -> Int -> Int) -> (Int -> ([Int] -> Int)) 
myFoldr (+) ::       Int -> ([Int] -> Int) 
myFoldr (+) 0 ::         [Int] -> Int 
sumListV3  ::         [Int] -> Int 

因爲sumListV3被定義爲myFoldr (+) 0,您可以在地方myFoldr (+) 0更換sumListV3那裏它被稱爲:

sumListV3 [1,2] 
    = (myFoldr (+) 0) [1,2] 
    = myFoldr (+) 0 [1,2] 
1

通常有定義的多種方式Haskell中的一個函數。在這種情況下,你可以使用(基本)模式匹配的參數xs

sumListV2 :: [Int] -> Int 
sumListV2 xs = myFoldr (+) 0 xs 

,在這種情況下,很相似,從概念,到「正常」 C風格的語法,在這種情況下的JavaScript。

var sumListV2 = function(xs) { 
    return myFoldr(plusFunc, 0, xs) 
} 

或者你也可以用其他函數的組合來定義函數,也稱爲無點式。

sumListV3 :: [Int] -> Int 
sumListV3 = myFoldr (+) 0 

在這種情況下,需要注意的是,在r.h.s.不是myFoldr的返回值,但是,因爲myFoldr已部分應用*具有其三個參數中的兩個參數,所以它是一個將剩餘的參數列表的函數。所以sumListV3被定義爲:一個函數,它需要一個列表。

在使用bind部分應用myFold時,可能會出現Javascript中的等效項。

約哈斯克爾
var sumListV2 = myFold.bind(null, plusFunc, 0); 

一個非常漂亮的事情是,這是語言內置的,所以你不需要額外的功能做的部分應用程序。關於Haskell的棘手問題,尤其是來自其他語言的問題是,您不需要額外的功能來執行部分應用程序;-)。棘手的,因爲模式匹配和部分應用程序的語法是如此相似,而在其他語言,他們是非常不同的。


*這不是給整個畫面,因爲它更準確地鑽研鑽營並在Haskell每個函數只需要一個參數的事實,而這需要3的功能是功能「鏈條」即返回函數。但我覺得這是一個有用的比喻,尤其是在與其他語言的部分應用進行比較時。