2016-05-01 37 views
0

在過去的兩個小時裏,我一直在閱讀有關Haskell中的currying和所有資源,介紹具有多個參數的函數實際上如何返回其他函數,但不知道它們的定義是如何形成的,所以這就是問題所在。Haskell Currying

讓我們定義函數:

myFunc :: (Num a) => a -> a -> a 
myFunc x y = x * 2 + x * y 

:t (myFunc 2)打印Num a => a -> a,即採用一個數量,並且還輸出一個數的函數。但是,(myFunc 2)返回的函數的定義是什麼樣的?定義中的編譯器是否替換爲x,而新功能是否變成myFunc' y = 2 * 2 + 2 * y

遞歸處理currying如何?如果我定義函數

replicate' :: (Integral i, Ord i) => i -> a -> [a] 
replicate' n x 
    | n <= 0 = [] 
    | otherwise = x : replicate' (n - 1) x 

,由(replicate' 3)在上下文(replicate 3) 'a'返回什麼功能?

回答

4

這是在明確咖喱形式定義replicate'

replicate' :: (Integral i, Ord i) => i -> (a -> [a]) 
replicate' n 
    | n <= 0  = const [] 
    | otherwise = \x -> x : replicate' (n - 1) x 

那麼,replicate' 3計算表達式

if 3 <= 0 then const [] 
       else \x -> x : replicate' 2 x 

這只是

\x -> x : replicate' 2 x 

如果它僅與定義「隱式柯里弗」,則編譯器可能會或可能不會拔出n <= 0條件出x綁定的,所以實際上你可能僅僅與

\x -> if 3 <= 0 then const [] 
        else \x -> x : replicate' 2 x 
+0

你能解釋一下'\ x - > x:replicate'2 x'是什麼意思?另外,編譯器是否按照我猜測的方式處理'myFunc'? –

+1

恩,你知道lambda函數是如何工作的,對吧?否則,這將是閱讀它們的好時機,它們非常重要。 – leftaroundabout

4

我想你混淆了兩個不同的東西

  • 討好
  • 部分功能應用

第一個是

     ------currying-----> 
     f :: (a,b) -> c      f' :: a -> b -> c 
         <----uncurrying----- 

轉化的功能,需要一個參數whi的元組 ch表示兩個事物相結合的一個參數 - 一個函數接受一個參數併產生一個函數!

如果您熟悉線性代數,那麼將雙線性函數看作是產生另一個線性函數的線性函數非常相似。

而部分功能應用程序只是明確親代化的結果。

f :: a -> b -> c 

真的

f :: a -> (b -> c) 

至少在定義函數的哈斯克爾方式。

+0

最終是否確定?根據維基百科的說法,「currying是一種將函數的​​評估轉化爲函數的技術,該函數將多個參數(或一個參數元組)用於評估一系列函數,每個函數都有一個參數」,並根據(https:// wiki .haskell.org/Partial_application),部分函數應用程序是當我創建一個函數,例如'func = replicate 3',它只給出'replicate'一個參數。調用'func var'會複製var三次。 –

+0

@RazvanMeriniuc根據你引用的維基百科文章,你不同意我的答案的哪一部分? – epsilonhalbe

+0

Currying不僅可以轉換元組,而且還可以轉換多個參數。你的第二個例子也是currying和部分功能應用程序出現在我以前介紹的上下文中。 –