2014-10-21 62 views
1

我刚刚开始阅读关于Haskell的一些信息,并且只编码了一点点,这意味着我是一个完整的Haskell新手。来自Haskell Wiki的项目Euler#2解决方案

项目欧拉问题#2如下:

在Fibonacci序列中的每个新项是通过将先前的两个术语生成。通过用1和2开始,第一10项将是:

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

通过考虑中的条款斐波纳契数列的值不超过四百万,找到偶数项的和。

我自己的第一步创建斐波纳契数字是一个天真(和慢/昂贵)。失败后,我去寻找解决方案。 Haskell Wiki has a solution。有几个,我发现第一个非常优雅 - 但我不完全理解它。这是我的代码(与在那里/小谎构建分裂出来的可读性和修修补补)

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只是不断打电话本身和中止条件是takeWhile呼叫的一部分。

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

更新

当然,我不是第一个问这个。 A very thourough explanation can be found elsewhere on SO

+4

此问题已在这里得到很好的回答:http://stackoverflow.com/questions/6273621/understanding-a-recursively-defined-list-fibs-in-terms-of-zipwith – 2014-10-21 22:34:12

+0

@ErikVesteraas谢谢你的链接,我专门搜索与欧拉相关的问题。 – stackmagic 2014-10-22 06:45:06

回答

4

fibs函数通过将列表左移1并将其添加到自身来工作。

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

现在哈斯克尔知道fibs = 1 : 1 : 2 : something,它可以继续为您无限地生成更多条款。