迭代函数不保存中间步骤?
我刚刚开始学习 Haskell,并作为练习进入了欧拉计划问题,其中对斐波那契数进行求和。我当前的方法是这个函数,它使用下一个元素创建一个新列表:
fib :: (Integral a) => [a] -> [a]
fib xs@(x1:x2:_) = (x1+x2) : xs
我找到了函数 iterate
,它在其结果上重新应用该函数。但是,结果是一个列表列表,[[2,1],[3,2,1],[5,3,2,1],..]
。当我对中间结果不感兴趣时,迭代
的替代方法是什么?我想对最后生成的数字执行一个 takeWhile
。这是完全错误的思考方式吗?
(我见过更好/更短/更漂亮的生成斐波那契序列的方法,所以我并不是真的在寻找关于 fib 函数的反馈 - 但我想让它工作,次优方法或不)
I just started learning Haskell, and as an exercise got into a Project Euler problem where Fibonacci numbers are summed. My current method is this function, which creates a new list with the next element:
fib :: (Integral a) => [a] -> [a]
fib xs@(x1:x2:_) = (x1+x2) : xs
I found the function iterate
which reapplies the function on it's result. However, the result is a list of lists, [[2,1],[3,2,1],[5,3,2,1],..]
. What is the alternative to iterate
when I'm not interested in the intermediate results? I want to do a takeWhile
with a condition on the last generated number. Is this the wrong way to think about it altogether?
(I've seen better/shorter/niftier ways of generating the Fibonacci sequence, so I'm not really looking for feedback on the fib
function - but I'd like to make it work, suboptimal method or not)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只需使用
迭代
!因为 Haskell 是一种纯语言,所以所有子列表都会共享,并且您基本上无需为生成所有这些迷你列表付出任何成本:[2, 1]
实际上是2, 1< /code> 在
[3, 2, 1]
中,依此类推。您实际上并不需要
takeWhile
,因为这会给您带来很多额外的麻烦,并且您仍然需要使用last
到达列表的末尾。相反,请使用find
。另请注意,如果您打算对结果列表进行求和,那么您就错过了
1
,因此您可能会失败。Just use
iterate
! Because Haskell is a pure language, all of the sublists get shared and you pay essentially no cost for having generated all of those mini lists:[2, 1]
is actually the2, 1
in[3, 2, 1]
, and so forth.You don't really want a
takeWhile
, because that will give you a lot of extra gunk and you'll still need to get to the end of the list withlast
. Instead, usefind
.Also note that if you're planning on summing the resulting list, you've missed a
1
so you'll be one off.我不确定
iterate
的使用,但请参阅过滤斐波那契Haskell 中的序列 了解如何过滤谎言列表。这是同一个家庭作业吗?
I'm not sure about the use of
iterate
, but see Filtering fibonacci sequence in Haskell for how to filter a list of fibs.Is this the same homework assignment?
我会使用“take”,因为每个连续的近似值都会比上一个更准确。然后你可以对其进行 (head .reverse) 操作。
请注意,如果您正在迭代的函数没有可计算的不动点,则“每个”结果都是中间结果。
I would use "take", since each successive approximation will be one integer more accurate than the last. You can then do (head . reverse) on that.
Note that "every" result is an intermediate result if the function you are iterating doesn't have a computable fixed point.
当在 Haskell 中需要一个函数时,只需定义它:)
下面的代码不是最优雅或最惯用的 Haskell,但它表明,如果需要的话,你总是可以使用尾递归循环手动完成任务,
我很确定那里有是使用折叠(或我忘记的库函数:))来做到这一点的更简洁的方法
When needing a function in Haskell just define it :)
The folowing isn't the most elegant or idiomatic Haskell, but serves to show that you can always do things by hand with a tail recursive loop if the need arises
I'm pretty sure there is a neater way to do this using folds (or a library function I forgot about :) )