迭代函数不保存中间步骤?

时间:2011-05-04 20:07:47

标签: haskell memoization

我刚刚开始学习Haskell,并且作为练习进入了项目Euler问题,其中Fibonacci数字被求和。我当前的方法是这个函数,它创建一个包含下一个元素的新列表:

fib :: (Integral a) => [a] -> [a]
fib xs@(x1:x2:_) = (x1+x2) : xs

我找到了函数iterate,它在结果上重新应用了函数。但是,结果是列表列表[[2,1],[3,2,1],[5,3,2,1],..]。当我对中间结果不感兴趣时​​,iterate的替代方案是什么?我想在最后生成的数字上做一个takeWhile条件。这是完全考虑它的错误方法吗?

(我已经看到了更好/更短/更简单的方法来生成Fibonacci序列,所以我不是真的在寻找关于fib函数的反馈 - 但我想让它工作,次优的方法或不)

4 个答案:

答案 0 :(得分:3)

只需使用iterate!由于Haskell是一种纯语言,所有子列表都可以共享,因此生成所有这些迷你列表基本上没有任何成本:[2, 1]实际上是2, 1中的[3, 2, 1],所以类推。

你真的不想要takeWhile,因为这会给你很多额外的垃圾,你仍然需要用last到达列表的末尾。相反,请使用find

另请注意,如果您计划对结果列表求和,那么您错过了1,因此您将成为其中一个。

答案 1 :(得分:0)

我不确定使用iterate,但请参阅Filtering fibonacci sequence in Haskell了解如何过滤虚拟列表。

这是相同的家庭作业吗?

答案 2 :(得分:0)

我会使用“take”,因为每个逐次逼近将比一个整数更准确。然后你就可以做(头部。反向)。

请注意,如果您正在迭代的函数没有可计算的固定点,则“每个”结果都是中间结果。

答案 3 :(得分:0)

在Haskell中需要一个函数时,只需定义它:)

下面的内容并不是最优雅或惯用的Haskell,但可以表明,如果需要,您可以随时使用尾递归循环手动完成任务

apply_n f n x =
    if n = 0 then x
    else apply_n' f (n-1) (f x)

n_th_fib n = apply_n fib n [1,1]

我很确定有一种更简洁的方法可以使用折叠(或我忘记的库函数:) :)