来自Haskell Wiki的项目Euler#2解决方案

时间:2014-10-21 22:24:52

标签: haskell

我刚刚开始阅读一些关于Haskell的内容,并且只编写了一小部分内容,这意味着我是一个完整的Haskell新手。

项目欧拉问题#2如下:

  

Fibonacci序列中的每个新术语都是通过添加前两个术语生成的。从1和2开始,前10个术语将是:

     

1,2,3,5,8,13,21,34,55,89,......

     

通过考虑Fibonacci序列中的值不超过四百万的项,找到偶数项的总和。

我自己创建斐波那契数字的第一步是一个天真的(和慢/昂贵的)。失败后,我去寻找解决方案。 Haskell Wiki has a solutionA very thourough explanation can be found elsewhere on SO。有几个,我发现第一个非常优雅 - 但我不完全理解它。这是我的代码(其中where / fibs构造被拆分以便于阅读和修改)

p :: Integer
p = sum [ x | x <- takeWhile (< 4000000) fibs, even x]

fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

main :: IO()
main = do
    print $ p
    -- BEWARE print $ fibs

当我使用print $ fibs运行时,它只是没有结束,这是我怀疑的,因为fibs只是一直在调用自己,而中止的条件是{{}的一部分1}}来电。

仅仅看一下fibs,它看起来就像函数已经返回它将返回的列表的一部分,但是它仍然添加了更多要附加到列表中的元素,它永远不会结束。这是一个人称之为无限列表,它可能也是我怀疑的尾递归? takeWhile函数如何工作?

更新

当然,我不是第一个问这个问题的人。 {{3}}

1 个答案:

答案 0 :(得分:4)

fibs函数的工作原理是将列表左移一个并将其添加到自身。

你告诉它fibs = 1 : 1 : something,并且可以告诉它tail fibs = 1 : something。因此zipWith (+) fibs (tail fibs)1+1=2开头。

现在haskell知道fibs = 1 : 1 : 2 : something,它可以继续无限制地生成更多的条款。