2013-07-04 121 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/一去)