这个listArray是如何填充的?

时间:2015-07-07 22:40:06

标签: haskell

使用暴力解决方案正确回答euler question 92后,我通过线程92阅读其他的haskell解决方案。最后一个解决方案速度非常快但让我难以理解它是如何实现一个数组,显示数字0到567是否归结为以1(False)或89(True)结尾的链。

import Data.List
import Data.Array
import Data.Char

b = (is89!) . sum . map ((^2) . digitToInt) . show
is89 = listArray (0, 567) $ False:False:(map b [2..88] ++ [True] ++ map b [90..567])

我认为我理解了haskell的惰性以及它可以使用列表中的先前值来生成未来值的方式,例如生成素数,斐波那契数等。但在这种情况下,索引似乎跳舞(在0到567的范围内)并且我迷失了索引的值如何结束False或True。

例如,第一个映射中的第一个值是2,当平方和求和时为4.但索引4尚未预先填充。就我所见,预先填充的唯一值是0,1和89。

有人可以慢慢地告诉我这个数组是如何填充的

1 个答案:

答案 0 :(得分:4)

Haskell的懒惰也只是计算每个值一次,而且这个数组是一种相当经典的记忆技术。

因此我们被要求计算is89 ! 2,我们检查数组并看到该元素尚未被评估,然后我们按照定义并看到要评估它,我们需要评估{{1}所以我们这样做。我们再一次检查数组,看看它还没有被评估。依此类推,我们检查is89 ! 41637,然后最终到达58,我们检查数组并查看该值已经过评估! (根据定义,它是89)。然后我们回溯并更新索引True以“评估”并包含58,依此类推True3716和{ {1}},这是我们回来时说的,我们被问到的价值是4

下次假设我们被问到2,我们检查数组,看看它还没有被评估,我们需要True,但我们之前已经评估过了!{1}}所以我们只使用过去的评估结果。

最后,我们实现了一个查找表,该表只填充了需要的值,即memoization。