Haskell缓存

use*_*611 2 caching haskell

解决Project Euler上的问题后,我在论坛中遇到了以下Haskell代码:

fillRow115 minLength = cache where
  cache = ((map fillRow115' [0 ..]) !!)
  fillRow115' 0 = 1
  fillRow115' cells = sum (map cache [0..cells-minLength]) + cache (cells-1)
Run Code Online (Sandbox Code Playgroud)

我本周刚开始学习Haskell,似乎无法理解这段代码.有人可以解释以下2项:

  1. 对我来说,看起来只有一个参数minLength,但该函数需要2个参数才能在ghci中运行.这另一个论点在哪里发挥作用?
  2. 从我在网上找到的!! 是列表索引运算符,并在调用时返回第n个元素[list] !! n.上面的代码似乎只用一个参数来调用它.那是做什么的?

PS如果有人想要复制此代码来解决Project Euler问题,它似乎没有给出正确的答案.

Tho*_*son 5

这另一个论点在哪里发挥作用?

让我们进一步简化这个问题.你可能知道这个head功能:

head [] = error "something bad"
head (x:_) = x
Run Code Online (Sandbox Code Playgroud)

你可能很傻并定义你自己的头部函数,只需调用head:

myHead xs = head xs
Run Code Online (Sandbox Code Playgroud)

并注意左侧和右侧都应用变量xs,因此我们可以执行所谓的eta-reduction并导致:

myHead = head
Run Code Online (Sandbox Code Playgroud)

类型签名可能会使点回家:

myHead :: [a] -> a
myHead = (head :: [a] -> a)
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,fillRow115需要第二个参数,因为它等于cache,这需要一个参数 - 这就把我们带到了你的第二个问题.

上面的代码似乎只用一个参数来调用它.那是做什么的?

考虑这个功能+.如果你想创建一个总是加2的函数,你可以"部分应用"2到函数+:

addTwo  = (+2)    -- (2+) would work just as well
Run Code Online (Sandbox Code Playgroud)

所以你正在查看列表索引功能!!:

(!!) :: [a] -> Int -> a
Run Code Online (Sandbox Code Playgroud)

并且对自己说,这只适用于某些列表.应用我们对部分应用程序的了解,我们得到了一种类型:

(someList !!) :: Int -> a
Run Code Online (Sandbox Code Playgroud)

所以这实际上是从Ints到列表元素的函数.

如果这还没有点击,只需替换someList你正在使用的列表:

someList = map fillRow115' [0..]
(someList !!) === ((map fillRow 115' [0..]) !!)
Run Code Online (Sandbox Code Playgroud)