我刚刚开始学习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
函数的反馈 - 但我想让它工作,次优的方法或不)
答案 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]
我很确定有一种更简洁的方法可以使用折叠(或我忘记的库函数:) :)