Haskell 哈斯克尔缓存
在解决了Euler项目的一个问题后,我在论坛上遇到了以下Haskell代码:Haskell 哈斯克尔缓存,haskell,caching,Haskell,Caching,在解决了Euler项目的一个问题后,我在论坛上遇到了以下Haskell代码: fillRow115 minLength = cache where cache = ((map fillRow115' [0 ..]) !!) fillRow115' 0 = 1 fillRow115' cells = sum (map cache [0..cells-minLength]) + cache (cells-1) 本周我刚开始学习Haskell,似乎无法理解这段代码。有人能解释一下以下两项
fillRow115 minLength = cache where
cache = ((map fillRow115' [0 ..]) !!)
fillRow115' 0 = 1
fillRow115' cells = sum (map cache [0..cells-minLength]) + cache (cells-1)
本周我刚开始学习Haskell,似乎无法理解这段代码。有人能解释一下以下两项吗
minLength
,但该函数需要两个参数才能在ghci中运行。这另一个论点在哪里起作用
是列表索引运算符,当被称为[list]时返回第n个元素!!n
。上面的代码似乎只使用一个参数调用它。那是干什么的另外,如果有人想复制此代码来解决Project Euler问题,它似乎没有给出正确的答案。此概念称为
部分应用程序
这是因为在Haskell中,所有函数实际上只有一个参数。
一个函数A->b->c
可能看起来像一个接受两个参数的函数
(一个是a型,一个是b型),但它实际上是一个函数a->(b->c)
,
i、 e.具有一个参数(类型a)的函数,返回一个采用参数(类型b)的函数。
见
(或者一般来说,试一试)这另一个论点在哪里起作用?
让我们进一步简化这个问题。您可能知道head
功能:
head [] = error "something bad"
head (x:_) = x
你可能会很傻,定义自己的head函数,只调用head
:
myHead xs = head xs
请注意,左侧和右侧都应用了变量xs
,因此我们可以进行所谓的eta减少,并导致:
myHead = head
类型签名可能会使这一点更加明确:
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
这实际上是一个从int到列表元素的函数
如果还没有单击,只需用您正在使用的列表替换someList
:
someList = map fillRow115' [0..]
(someList !!) === ((map fillRow 115' [0..]) !!)