2013-07-04 115 views
2

解決上項目歐拉一個問題,我在論壇上遇到下列Haskell代碼來後:哈斯克爾緩存

fillRow115 minLength = cache where 
    cache = ((map fillRow115' [0 ..]) !!) 
    fillRow115' 0 = 1 
    fillRow115' cells = sum (map cache [0..cells-minLength]) + cache (cells-1) 

我剛開始這個星期的學習Haskell和似乎無法理解這段代碼。可有人請解釋以下2項:

  1. 對我來說,它看起來像只有一個參數minLength,但功能需要兩個參數在ghci中運行。這個其他論點在哪裏起作用?
  2. 從我能在網上找到的,!!是列表索引運算符,當調用[list] !! n時返回第n個元素。上面的代碼似乎只用一個參數來調用它。那是幹什麼的?

P.S.如果有人想拷貝這些代碼來解決Project Euler問題,它似乎沒有給出正確的答案。

回答

5

哪裏這另一種說法來發揮作用?

讓我們進一步簡化這個問題。你可能知道的head功能:

head [] = error "something bad" 
head (x:_) = x 

你可能是愚蠢的,定義自己的頭功能,只是調用head

myHead xs = head xs 

同時注意左邊和右邊應用可變xs,所以我們可以做所謂的eta還原,並導致:

myHead = head 

類型簽名可能會破壞po INT家:

myHead :: [a] -> a 
myHead = (head :: [a] -> a) 

所以你的情況,fillRow115需要第二個參數,因爲它等於cache,這需要一個參數 - 這給我們帶來了第二個問題。

上面的代碼似乎只用一個參數來調用它。那是幹什麼的?

考慮功能+。如果你想使一個函數,總是添加2,你可以在「局部應用」 2的功能+

addTwo = (+2) -- (2+) would work just as well 

那麼您正在尋找在列表索引功能!!

(!!) :: [a] -> Int -> a 

,並說對你自己來說,這只是被應用到某個列表中。應用我們知道的部分應用我們得到一種類型:

(someList !!) :: Int -> a 

所以這實際上是一個從Ints到列表元素的函數。

如果不點擊的是,只需更換someList與列表中,您正在使用:

someList = map fillRow115' [0..] 
(someList !!) === ((map fillRow 115' [0..]) !!) 
2

這個概念被稱爲partial application
它的工作原理是因爲在Haskell中,所有函數實際上只有一個參數。
函數a -> b -> c可能看起來像是取兩個參數
(typa中的一個,和b型之一)的功能,但它是一個真正的函數a -> (b -> c)
即用一個paramater(類型的)的函數返回一個帶有參數(類型b)的函數。

http://www.haskell.org/haskellwiki/Partial_application
(或只是一般,給http://learnyouahaskell.com/一去)