Generating Fibonacci numbers in Haskell?












46















In Haskell, how can I generate Fibonacci numbers based on the property that the nth Fibonacci number is equal to the (n-2)th Fibonacci number plus the (n-1)th Fibonacci number?



I've seen this:



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


I don't really understand that, or how it produces an infinite list instead of one containing 3 elements.



How would I write haskell code that works by calculating the actual definition and not by doing something really weird with list functions?










share|improve this question




















  • 8





    You're missing all the fun of Haskell if you avoid the "weird" list functions. But for what it's worth, there's a good explanation of how the recursion works in the above code here: scienceblogs.com/goodmath/2006/11/…

    – rtperson
    Jul 9 '09 at 20:58






  • 4





    The article @rtperson links to is now at scienceblogs.com/goodmath/2006/11/28/… .

    – Ben
    Jan 2 '16 at 23:57
















46















In Haskell, how can I generate Fibonacci numbers based on the property that the nth Fibonacci number is equal to the (n-2)th Fibonacci number plus the (n-1)th Fibonacci number?



I've seen this:



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


I don't really understand that, or how it produces an infinite list instead of one containing 3 elements.



How would I write haskell code that works by calculating the actual definition and not by doing something really weird with list functions?










share|improve this question




















  • 8





    You're missing all the fun of Haskell if you avoid the "weird" list functions. But for what it's worth, there's a good explanation of how the recursion works in the above code here: scienceblogs.com/goodmath/2006/11/…

    – rtperson
    Jul 9 '09 at 20:58






  • 4





    The article @rtperson links to is now at scienceblogs.com/goodmath/2006/11/28/… .

    – Ben
    Jan 2 '16 at 23:57














46












46








46


19






In Haskell, how can I generate Fibonacci numbers based on the property that the nth Fibonacci number is equal to the (n-2)th Fibonacci number plus the (n-1)th Fibonacci number?



I've seen this:



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


I don't really understand that, or how it produces an infinite list instead of one containing 3 elements.



How would I write haskell code that works by calculating the actual definition and not by doing something really weird with list functions?










share|improve this question
















In Haskell, how can I generate Fibonacci numbers based on the property that the nth Fibonacci number is equal to the (n-2)th Fibonacci number plus the (n-1)th Fibonacci number?



I've seen this:



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


I don't really understand that, or how it produces an infinite list instead of one containing 3 elements.



How would I write haskell code that works by calculating the actual definition and not by doing something really weird with list functions?







haskell fibonacci






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 28 '17 at 15:35









Adam Stelmaszczyk

15.5k35498




15.5k35498










asked Jul 9 '09 at 18:41









LuckyLucky

2,20763248




2,20763248








  • 8





    You're missing all the fun of Haskell if you avoid the "weird" list functions. But for what it's worth, there's a good explanation of how the recursion works in the above code here: scienceblogs.com/goodmath/2006/11/…

    – rtperson
    Jul 9 '09 at 20:58






  • 4





    The article @rtperson links to is now at scienceblogs.com/goodmath/2006/11/28/… .

    – Ben
    Jan 2 '16 at 23:57














  • 8





    You're missing all the fun of Haskell if you avoid the "weird" list functions. But for what it's worth, there's a good explanation of how the recursion works in the above code here: scienceblogs.com/goodmath/2006/11/…

    – rtperson
    Jul 9 '09 at 20:58






  • 4





    The article @rtperson links to is now at scienceblogs.com/goodmath/2006/11/28/… .

    – Ben
    Jan 2 '16 at 23:57








8




8





You're missing all the fun of Haskell if you avoid the "weird" list functions. But for what it's worth, there's a good explanation of how the recursion works in the above code here: scienceblogs.com/goodmath/2006/11/…

– rtperson
Jul 9 '09 at 20:58





You're missing all the fun of Haskell if you avoid the "weird" list functions. But for what it's worth, there's a good explanation of how the recursion works in the above code here: scienceblogs.com/goodmath/2006/11/…

– rtperson
Jul 9 '09 at 20:58




4




4





The article @rtperson links to is now at scienceblogs.com/goodmath/2006/11/28/… .

– Ben
Jan 2 '16 at 23:57





The article @rtperson links to is now at scienceblogs.com/goodmath/2006/11/28/… .

– Ben
Jan 2 '16 at 23:57












9 Answers
9






active

oldest

votes


















78














Here's a different and simpler function that calculates the n'th Fibonacci number:



fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)


The implementation you are referring to relays on some observations about how values in Fibonacci relate to each other (and how Haskell can define data structures in terms of themselfs in effect creating infinite data structures)



The function in your question works like this:



Assume you already had an infinite list of the Fibonacci numbers:



   [ 1, 1, 2, 3, 5,  8, 13, .... ]


The tail of this list is



   [ 1, 2, 3, 5, 8, 13, 21, .... ]


zipWith combines two lists element by element using the given operator:



   [ 1, 1, 2, 3,  5,  8, 13, .... ]
+ [ 1, 2, 3, 5, 8, 13, 21, .... ]
= [ 2, 3, 5, 8, 13, 21, 34, .... ]


So the infinite list of Fibonacci numbers can be calculated by prepending the elements 1 and 1 to the result of zipping the infinite list of Fibonacci numbers with the tail of the infinite list of Fibonacci numbers using the + operator.



Now, to get the n'th Fibonacci number, just get the n'th element of the infinite list of Fibonacci numbers:



fib n = fibs !! n


The beauty of Haskell is that it doesn't calculate any element of the list of Fibonacci numbers until its needed.



Did I make your head explode? :)






share|improve this answer





















  • 24





    I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

    – Steve B.
    Jul 9 '09 at 19:04






  • 2





    fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

    – Christopher Done
    Feb 5 '10 at 21:01






  • 3





    @Christopher sometimes the first 0 of the sequence is omitted.

    – Yacoby
    Mar 12 '10 at 12:40








  • 3





    @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

    – Daniel Fischer
    Jan 19 '12 at 6:17






  • 2





    @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

    – semicolon
    Feb 11 '16 at 0:27





















20














going by the definition, every item of the fibonacci series is the sum of the previous two terms. putting this definition in to lazy haskell gives u this!



fibo a b = a:fibo b (a+b)


now just take n items from fibo starting with 0,1



take 10 (fibo 0 1)





share|improve this answer



















  • 1





    i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

    – Will Ness
    Feb 6 '14 at 21:38











  • Best answer! Should be the accepted one.

    – jhegedus
    Oct 18 '16 at 9:44











  • for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

    – Wolf
    Jul 17 '17 at 10:08











  • What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

    – Wolf
    Jul 17 '17 at 10:34













  • That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

    – fp_mora
    Mar 7 '18 at 0:02



















19














To expand on dtb's answer:



There is an important difference between the "simple" solution:



fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)


And the one you specified:



fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


The simple solution takes O(1.618NN) time to compute the Nth element, while the one you specified takes O(N2). That's because the one you specified takes into account that computing fib n and fib (n-1) (which is required to compute it) share the dependency of fib (n-2), and that it can be computed once for both to save time. O(N2) is for N additions of numbers of O(N) digits.






share|improve this answer


























  • @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

    – yairchu
    Jul 10 '09 at 5:31






  • 1





    @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

    – Chris Conway
    Jul 10 '09 at 14:54











  • okay i misread the question. i see that you already said what i was trying to say

    – newacct
    Jul 10 '09 at 18:07






  • 2





    Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

    – Zelphir
    Feb 11 '16 at 1:45






  • 2





    @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

    – yairchu
    Feb 15 '16 at 11:45



















5














There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after.






share|improve this answer































    1














    The definition of fibonaci(n) is:



    fibonacci (n) = fibonacci (n-1) + fibonacci (n-2)



    The naive implementation in Haskell



    fibonacci :: Integer -> Integer
    fibonacci 0 = 1
    fibonacci 1 = 1
    fibonacci x = fibonacci (x-1) + fibonacci (x-2)


    All formulas can be traced back to this definition, some which run very quickly, some of which run very slowly. The implementation above has O(n) = 2^n



    In the spirit of your question, let me remove the use of lists and give you something that runs in O(n) I.e. let's not hold all the fibonaccis from 0 to n in a list.



    If we have a triple (a tuple with three members) that looks like:



    (n, fibonacci[n-1], fibonacci[n])



    Remembering the initial definition, we can calculate the next triple from the last triple:



    (n+1, fibonacci[n], fibonacci[n-1] + fibonacci[n])
    = (n+1, fibonacci[n], fibonacci[n+1])



    And the next triple from the last triple:
    (n+2, fibonacci[n+1], fibonacci[n] + fibonacci[n+1])
    = (n+1, fibonacci[n+1], fibonacci[n+2])



    And so on...



    n = 0 => (0,0,1) 
    n = 1 => (1,1,1) - calculated from the previous triple
    n = 2 => (2,1,2) - calculated from the previous triple
    n = 3 => (3,2,3) - calculated from the previous triple
    n = 4 => (4,3,5) - calculated from the previous triple
    n = 5 => (5,5,8) - calculated from the previous triple


    Let's implement this in Haskell and use self explanatory variable names:



    nextTripleIfCurrentNIsLessThanN :: (Int, Integer, Integer) -> Int -> (Int, Integer, Integer)
    nextTripleIfCurrentNIsLessThanN (currentN, x, y) n = if currentN < n
    then nextTripleIfCurrentNIsLessThanN (currentN + 1, y, x + y) n
    else (currentN, x, y)

    thirdElementOfTriple :: (x,y,z) -> z
    thirdElementOfTriple (x,y,z) = z

    fibonacci :: Int -> Integer
    fibonacci n = thirdElementOfTriple (nextTripleIfCurrentNIsLessThanN (0,0,1) n)


    This will work in O(n) [It is mildly quadratic which shows up in large numbers. The reason for that is that adding big numbers is more costly than adding small ones. But that's a separate discussion about model of computation.]



    fibonacci 0
    1
    fibonacci 1
    1
    fibonacci 2
    2
    fibonacci 3
    3
    fibonacci 4
    5
    fibonacci 5
    8
    fibonacci 5000
    6276302800488957086035253108349684055478528702736457439025824448927937256811663264475883711527806250329984690249846819800648580083040107584710332687596562185073640422286799239932615797105974710857095487342820351307477141875012176874307156016229965832589137779724973854362777629878229505500260477136108363709090010421536915488632339240756987974122598603591920306874926755600361865354330444681915154695741851960071089944015319300128574107662757054790648152751366475529121877212785489665101733755898580317984402963873738187000120737824193162011399200547424034440836239726275765901190914513013217132050988064832024783370583789324109052449717186857327239783000020791777804503930439875068662687670678802914269784817022567088069496231111407908953313902398529655056082228598715882365779469902465675715699187225655878240668599547496218159297881601061923195562143932693324644219266564617042934227893371179832389642895285401263875342640468017378925921483580111278055044254198382265567395946431803304304326865077742925818757370691726168228648841319231470626





    share|improve this answer

































      1














      This implementation calculates 100,000th Fibonacci number almost instantly:



      fib = fastFib 1 1

      fastFib _ _ 0 = 0
      fastFib _ _ 1 = 1
      fastFib _ _ 2 = 1
      fastFib a b 3 = a + b
      fastFib a b c = fastFib (a + b) a (c - 1)





      share|improve this answer































        0














        A lazy way of generating infinite Fibonacci series can easily be achieved by unfoldr as follows;



        fibs :: [Integer]
        fibs = unfoldr ((f,s) -> Just (f,(s,f+s))) (0,1)





        share|improve this answer































          0














          LOL, I love Haskell pattern matching but it is rendered useless in standard Fibonacci functions. The standard list is constructed from the right. To use pattern matching and cons, the list must be constructed from the left. Well, one consolation, at least, is this is really fast. ~O(n), it should be. A helper function is needed to reverse the infinite list (things you can only do in Haskell, joy) and this function outputs each subsequent list of the run so 'last' is also used in the helper function pipeline.



          f (x:y:xs) = (x+y):(x:(y:xs))


          The helper



          fib n = reverse . last . take n $ iterate f [1,0]


          This is a list version and, I think, it explicates how the list is constructed which is the purpose. I want to do a tuple version.



          Edit 3/15/2018



          First off, Will Ness enlightened me with the knowledge that an entire list being generated at each iteration was unnecessary and that only the last two values used were needed and that the values for the result list were the first values of each list or pair generated. It was so funny. After Will told me the values for the list were the first values of the lists, I ran it and saw the values 0,1,1,2,3,5,8,13 as each head of each list, I said WTF, did Will change my code on my PC? The values were there but how!? After a while, I realized they were there all along but I just didn't see them. ugh.
          Will's version of the function and helper function are:



          f = ((x:y:xs) -> (x+y):x:xs) -- notice, no y: put back only x+y & x


          and his helper function rewrite



          fib n = map head . take n $iterate f [0,1]


          I think, too, that they now can be combined:



          fib n = take n . map head $ iterate ((x:y:xs) -> (x+y):x:xs) [0,1]


          As an irrelevant aside, the function can be with tuples, too



          fib n = take n . map fst $ iterate ((a,b) -> (b,a+b)) (0,1)


          Another form, a list comprehension form, can also be written for all:



          fib n = take n [ fst t | t <- iterate ((a,b) -> (b,a+b)) (0,1)]


          These are all iterative and robust. The fastest is the map with lists at 12.23 seconds for fib 5000. The tuple comprehension was second fastest for fib 5000 at 13.58 seconds.






          share|improve this answer


























          • haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

            – Will Ness
            Mar 12 '18 at 14:20













          • It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

            – fp_mora
            Mar 13 '18 at 16:51











          • try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

            – Will Ness
            Mar 13 '18 at 17:23













          • want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

            – Will Ness
            Mar 13 '18 at 17:56











          • @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

            – fp_mora
            Mar 13 '18 at 17:57



















          -1














          using iterate



          fibonaci = map fst (iterate f (0,1)) where f (x,y) = (y,x+y)


          using



          take 10 fibonaci

          [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]





          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1105765%2fgenerating-fibonacci-numbers-in-haskell%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            9 Answers
            9






            active

            oldest

            votes








            9 Answers
            9






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            78














            Here's a different and simpler function that calculates the n'th Fibonacci number:



            fib :: Integer -> Integer
            fib 0 = 0
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            The implementation you are referring to relays on some observations about how values in Fibonacci relate to each other (and how Haskell can define data structures in terms of themselfs in effect creating infinite data structures)



            The function in your question works like this:



            Assume you already had an infinite list of the Fibonacci numbers:



               [ 1, 1, 2, 3, 5,  8, 13, .... ]


            The tail of this list is



               [ 1, 2, 3, 5, 8, 13, 21, .... ]


            zipWith combines two lists element by element using the given operator:



               [ 1, 1, 2, 3,  5,  8, 13, .... ]
            + [ 1, 2, 3, 5, 8, 13, 21, .... ]
            = [ 2, 3, 5, 8, 13, 21, 34, .... ]


            So the infinite list of Fibonacci numbers can be calculated by prepending the elements 1 and 1 to the result of zipping the infinite list of Fibonacci numbers with the tail of the infinite list of Fibonacci numbers using the + operator.



            Now, to get the n'th Fibonacci number, just get the n'th element of the infinite list of Fibonacci numbers:



            fib n = fibs !! n


            The beauty of Haskell is that it doesn't calculate any element of the list of Fibonacci numbers until its needed.



            Did I make your head explode? :)






            share|improve this answer





















            • 24





              I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

              – Steve B.
              Jul 9 '09 at 19:04






            • 2





              fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

              – Christopher Done
              Feb 5 '10 at 21:01






            • 3





              @Christopher sometimes the first 0 of the sequence is omitted.

              – Yacoby
              Mar 12 '10 at 12:40








            • 3





              @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

              – Daniel Fischer
              Jan 19 '12 at 6:17






            • 2





              @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

              – semicolon
              Feb 11 '16 at 0:27


















            78














            Here's a different and simpler function that calculates the n'th Fibonacci number:



            fib :: Integer -> Integer
            fib 0 = 0
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            The implementation you are referring to relays on some observations about how values in Fibonacci relate to each other (and how Haskell can define data structures in terms of themselfs in effect creating infinite data structures)



            The function in your question works like this:



            Assume you already had an infinite list of the Fibonacci numbers:



               [ 1, 1, 2, 3, 5,  8, 13, .... ]


            The tail of this list is



               [ 1, 2, 3, 5, 8, 13, 21, .... ]


            zipWith combines two lists element by element using the given operator:



               [ 1, 1, 2, 3,  5,  8, 13, .... ]
            + [ 1, 2, 3, 5, 8, 13, 21, .... ]
            = [ 2, 3, 5, 8, 13, 21, 34, .... ]


            So the infinite list of Fibonacci numbers can be calculated by prepending the elements 1 and 1 to the result of zipping the infinite list of Fibonacci numbers with the tail of the infinite list of Fibonacci numbers using the + operator.



            Now, to get the n'th Fibonacci number, just get the n'th element of the infinite list of Fibonacci numbers:



            fib n = fibs !! n


            The beauty of Haskell is that it doesn't calculate any element of the list of Fibonacci numbers until its needed.



            Did I make your head explode? :)






            share|improve this answer





















            • 24





              I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

              – Steve B.
              Jul 9 '09 at 19:04






            • 2





              fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

              – Christopher Done
              Feb 5 '10 at 21:01






            • 3





              @Christopher sometimes the first 0 of the sequence is omitted.

              – Yacoby
              Mar 12 '10 at 12:40








            • 3





              @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

              – Daniel Fischer
              Jan 19 '12 at 6:17






            • 2





              @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

              – semicolon
              Feb 11 '16 at 0:27
















            78












            78








            78







            Here's a different and simpler function that calculates the n'th Fibonacci number:



            fib :: Integer -> Integer
            fib 0 = 0
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            The implementation you are referring to relays on some observations about how values in Fibonacci relate to each other (and how Haskell can define data structures in terms of themselfs in effect creating infinite data structures)



            The function in your question works like this:



            Assume you already had an infinite list of the Fibonacci numbers:



               [ 1, 1, 2, 3, 5,  8, 13, .... ]


            The tail of this list is



               [ 1, 2, 3, 5, 8, 13, 21, .... ]


            zipWith combines two lists element by element using the given operator:



               [ 1, 1, 2, 3,  5,  8, 13, .... ]
            + [ 1, 2, 3, 5, 8, 13, 21, .... ]
            = [ 2, 3, 5, 8, 13, 21, 34, .... ]


            So the infinite list of Fibonacci numbers can be calculated by prepending the elements 1 and 1 to the result of zipping the infinite list of Fibonacci numbers with the tail of the infinite list of Fibonacci numbers using the + operator.



            Now, to get the n'th Fibonacci number, just get the n'th element of the infinite list of Fibonacci numbers:



            fib n = fibs !! n


            The beauty of Haskell is that it doesn't calculate any element of the list of Fibonacci numbers until its needed.



            Did I make your head explode? :)






            share|improve this answer















            Here's a different and simpler function that calculates the n'th Fibonacci number:



            fib :: Integer -> Integer
            fib 0 = 0
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            The implementation you are referring to relays on some observations about how values in Fibonacci relate to each other (and how Haskell can define data structures in terms of themselfs in effect creating infinite data structures)



            The function in your question works like this:



            Assume you already had an infinite list of the Fibonacci numbers:



               [ 1, 1, 2, 3, 5,  8, 13, .... ]


            The tail of this list is



               [ 1, 2, 3, 5, 8, 13, 21, .... ]


            zipWith combines two lists element by element using the given operator:



               [ 1, 1, 2, 3,  5,  8, 13, .... ]
            + [ 1, 2, 3, 5, 8, 13, 21, .... ]
            = [ 2, 3, 5, 8, 13, 21, 34, .... ]


            So the infinite list of Fibonacci numbers can be calculated by prepending the elements 1 and 1 to the result of zipping the infinite list of Fibonacci numbers with the tail of the infinite list of Fibonacci numbers using the + operator.



            Now, to get the n'th Fibonacci number, just get the n'th element of the infinite list of Fibonacci numbers:



            fib n = fibs !! n


            The beauty of Haskell is that it doesn't calculate any element of the list of Fibonacci numbers until its needed.



            Did I make your head explode? :)







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 24 '18 at 21:39









            przemo_li

            2,53732440




            2,53732440










            answered Jul 9 '09 at 18:57









            dtbdtb

            172k26345402




            172k26345402








            • 24





              I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

              – Steve B.
              Jul 9 '09 at 19:04






            • 2





              fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

              – Christopher Done
              Feb 5 '10 at 21:01






            • 3





              @Christopher sometimes the first 0 of the sequence is omitted.

              – Yacoby
              Mar 12 '10 at 12:40








            • 3





              @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

              – Daniel Fischer
              Jan 19 '12 at 6:17






            • 2





              @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

              – semicolon
              Feb 11 '16 at 0:27
















            • 24





              I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

              – Steve B.
              Jul 9 '09 at 19:04






            • 2





              fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

              – Christopher Done
              Feb 5 '10 at 21:01






            • 3





              @Christopher sometimes the first 0 of the sequence is omitted.

              – Yacoby
              Mar 12 '10 at 12:40








            • 3





              @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

              – Daniel Fischer
              Jan 19 '12 at 6:17






            • 2





              @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

              – semicolon
              Feb 11 '16 at 0:27










            24




            24





            I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

            – Steve B.
            Jul 9 '09 at 19:04





            I love that - calculate the list by summing the corresponding values of the list you're trying to figure out. My brain doesn't ordinarily work like that - it's like trying to look inside your own ear.

            – Steve B.
            Jul 9 '09 at 19:04




            2




            2





            fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

            – Christopher Done
            Feb 5 '10 at 21:01





            fib 0 = 1 should be fib 0 = 0. I only noticed this because I just this second made the same mistake. Haha.

            – Christopher Done
            Feb 5 '10 at 21:01




            3




            3





            @Christopher sometimes the first 0 of the sequence is omitted.

            – Yacoby
            Mar 12 '10 at 12:40







            @Christopher sometimes the first 0 of the sequence is omitted.

            – Yacoby
            Mar 12 '10 at 12:40






            3




            3





            @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

            – Daniel Fischer
            Jan 19 '12 at 6:17





            @Abarax No, in fact tail recursion would make the trick impossible. It's laziness and guarded recursion, the recursive call is in each step in a constructor field, fibo : recursive_call, so to reach it, we have to deconstruct the result of the previous call. Thus the recursion depth is never larger than 1.

            – Daniel Fischer
            Jan 19 '12 at 6:17




            2




            2





            @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

            – semicolon
            Feb 11 '16 at 0:27







            @Zelphir You are generating the infinite list with 0 : 1 : zipWith (+) fibs (tail fibs). You start with [0, 1...] and append zipWith (+) fibs (tail fibs) to it. The first element of fibs is 0 and the first element of tail fibs is 10 so the next element is 0 + 1 = 1` giving you [0, 1, 1...] and now you get the second element of zipWith ... which is 1 + 1 = 2 giving you [0, 1, 1, 2...] and so on.

            – semicolon
            Feb 11 '16 at 0:27















            20














            going by the definition, every item of the fibonacci series is the sum of the previous two terms. putting this definition in to lazy haskell gives u this!



            fibo a b = a:fibo b (a+b)


            now just take n items from fibo starting with 0,1



            take 10 (fibo 0 1)





            share|improve this answer



















            • 1





              i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

              – Will Ness
              Feb 6 '14 at 21:38











            • Best answer! Should be the accepted one.

              – jhegedus
              Oct 18 '16 at 9:44











            • for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

              – Wolf
              Jul 17 '17 at 10:08











            • What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

              – Wolf
              Jul 17 '17 at 10:34













            • That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

              – fp_mora
              Mar 7 '18 at 0:02
















            20














            going by the definition, every item of the fibonacci series is the sum of the previous two terms. putting this definition in to lazy haskell gives u this!



            fibo a b = a:fibo b (a+b)


            now just take n items from fibo starting with 0,1



            take 10 (fibo 0 1)





            share|improve this answer



















            • 1





              i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

              – Will Ness
              Feb 6 '14 at 21:38











            • Best answer! Should be the accepted one.

              – jhegedus
              Oct 18 '16 at 9:44











            • for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

              – Wolf
              Jul 17 '17 at 10:08











            • What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

              – Wolf
              Jul 17 '17 at 10:34













            • That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

              – fp_mora
              Mar 7 '18 at 0:02














            20












            20








            20







            going by the definition, every item of the fibonacci series is the sum of the previous two terms. putting this definition in to lazy haskell gives u this!



            fibo a b = a:fibo b (a+b)


            now just take n items from fibo starting with 0,1



            take 10 (fibo 0 1)





            share|improve this answer













            going by the definition, every item of the fibonacci series is the sum of the previous two terms. putting this definition in to lazy haskell gives u this!



            fibo a b = a:fibo b (a+b)


            now just take n items from fibo starting with 0,1



            take 10 (fibo 0 1)






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Feb 6 '14 at 14:31









            renjithrenjith

            346137




            346137








            • 1





              i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

              – Will Ness
              Feb 6 '14 at 21:38











            • Best answer! Should be the accepted one.

              – jhegedus
              Oct 18 '16 at 9:44











            • for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

              – Wolf
              Jul 17 '17 at 10:08











            • What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

              – Wolf
              Jul 17 '17 at 10:34













            • That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

              – fp_mora
              Mar 7 '18 at 0:02














            • 1





              i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

              – Will Ness
              Feb 6 '14 at 21:38











            • Best answer! Should be the accepted one.

              – jhegedus
              Oct 18 '16 at 9:44











            • for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

              – Wolf
              Jul 17 '17 at 10:08











            • What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

              – Wolf
              Jul 17 '17 at 10:34













            • That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

              – fp_mora
              Mar 7 '18 at 0:02








            1




            1





            i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

            – Will Ness
            Feb 6 '14 at 21:38





            i.e. a, b = (0,1) : (b, a+b) or in Haskell, map fst $ (((a,b)->(b,a+b)) iterate` (0,1))`. :)

            – Will Ness
            Feb 6 '14 at 21:38













            Best answer! Should be the accepted one.

            – jhegedus
            Oct 18 '16 at 9:44





            Best answer! Should be the accepted one.

            – jhegedus
            Oct 18 '16 at 9:44













            for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

            – Wolf
            Jul 17 '17 at 10:08





            for fibs = map fst $ iterate ((a,b) -> (b,a+b)) (0,1) see wiki.haskell.org/The_Fibonacci_sequence#With_iterate

            – Wolf
            Jul 17 '17 at 10:08













            What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

            – Wolf
            Jul 17 '17 at 10:34







            What is the computational complexity compared to fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ?

            – Wolf
            Jul 17 '17 at 10:34















            That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

            – fp_mora
            Mar 7 '18 at 0:02





            That is one beautiful function and beauty is everything in math and programming. The simplicity and cogency is remarkable. It is poetic, compact and full of meaning.

            – fp_mora
            Mar 7 '18 at 0:02











            19














            To expand on dtb's answer:



            There is an important difference between the "simple" solution:



            fib 0 = 1
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            And the one you specified:



            fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


            The simple solution takes O(1.618NN) time to compute the Nth element, while the one you specified takes O(N2). That's because the one you specified takes into account that computing fib n and fib (n-1) (which is required to compute it) share the dependency of fib (n-2), and that it can be computed once for both to save time. O(N2) is for N additions of numbers of O(N) digits.






            share|improve this answer


























            • @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

              – yairchu
              Jul 10 '09 at 5:31






            • 1





              @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

              – Chris Conway
              Jul 10 '09 at 14:54











            • okay i misread the question. i see that you already said what i was trying to say

              – newacct
              Jul 10 '09 at 18:07






            • 2





              Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

              – Zelphir
              Feb 11 '16 at 1:45






            • 2





              @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

              – yairchu
              Feb 15 '16 at 11:45
















            19














            To expand on dtb's answer:



            There is an important difference between the "simple" solution:



            fib 0 = 1
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            And the one you specified:



            fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


            The simple solution takes O(1.618NN) time to compute the Nth element, while the one you specified takes O(N2). That's because the one you specified takes into account that computing fib n and fib (n-1) (which is required to compute it) share the dependency of fib (n-2), and that it can be computed once for both to save time. O(N2) is for N additions of numbers of O(N) digits.






            share|improve this answer


























            • @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

              – yairchu
              Jul 10 '09 at 5:31






            • 1





              @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

              – Chris Conway
              Jul 10 '09 at 14:54











            • okay i misread the question. i see that you already said what i was trying to say

              – newacct
              Jul 10 '09 at 18:07






            • 2





              Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

              – Zelphir
              Feb 11 '16 at 1:45






            • 2





              @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

              – yairchu
              Feb 15 '16 at 11:45














            19












            19








            19







            To expand on dtb's answer:



            There is an important difference between the "simple" solution:



            fib 0 = 1
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            And the one you specified:



            fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


            The simple solution takes O(1.618NN) time to compute the Nth element, while the one you specified takes O(N2). That's because the one you specified takes into account that computing fib n and fib (n-1) (which is required to compute it) share the dependency of fib (n-2), and that it can be computed once for both to save time. O(N2) is for N additions of numbers of O(N) digits.






            share|improve this answer















            To expand on dtb's answer:



            There is an important difference between the "simple" solution:



            fib 0 = 1
            fib 1 = 1
            fib n = fib (n-1) + fib (n-2)


            And the one you specified:



            fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


            The simple solution takes O(1.618NN) time to compute the Nth element, while the one you specified takes O(N2). That's because the one you specified takes into account that computing fib n and fib (n-1) (which is required to compute it) share the dependency of fib (n-2), and that it can be computed once for both to save time. O(N2) is for N additions of numbers of O(N) digits.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 23 '17 at 12:34









            Community

            11




            11










            answered Jul 9 '09 at 21:05









            yairchuyairchu

            15.7k75995




            15.7k75995













            • @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

              – yairchu
              Jul 10 '09 at 5:31






            • 1





              @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

              – Chris Conway
              Jul 10 '09 at 14:54











            • okay i misread the question. i see that you already said what i was trying to say

              – newacct
              Jul 10 '09 at 18:07






            • 2





              Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

              – Zelphir
              Feb 11 '16 at 1:45






            • 2





              @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

              – yairchu
              Feb 15 '16 at 11:45



















            • @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

              – yairchu
              Jul 10 '09 at 5:31






            • 1





              @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

              – Chris Conway
              Jul 10 '09 at 14:54











            • okay i misread the question. i see that you already said what i was trying to say

              – newacct
              Jul 10 '09 at 18:07






            • 2





              Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

              – Zelphir
              Feb 11 '16 at 1:45






            • 2





              @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

              – yairchu
              Feb 15 '16 at 11:45

















            @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

            – yairchu
            Jul 10 '09 at 5:31





            @newacct: If you only want "fibs !! n", you need to calculative all of "take n fibs", n items, with a calculation of O(n) each because adding two numbers of O(n) digits is O(n).

            – yairchu
            Jul 10 '09 at 5:31




            1




            1





            @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

            – Chris Conway
            Jul 10 '09 at 14:54





            @newacct: You're assuming that every distinct dynamic occurrence of "fib k" (where k is a constant) is merged into a single thunk. GHC might be smart enough to do that in this case, but I don't think it's guaranteed.

            – Chris Conway
            Jul 10 '09 at 14:54













            okay i misread the question. i see that you already said what i was trying to say

            – newacct
            Jul 10 '09 at 18:07





            okay i misread the question. i see that you already said what i was trying to say

            – newacct
            Jul 10 '09 at 18:07




            2




            2





            Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

            – Zelphir
            Feb 11 '16 at 1:45





            Why not simply say the golden ratio (Phi) instead of imprecise 1.618?

            – Zelphir
            Feb 11 '16 at 1:45




            2




            2





            @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

            – yairchu
            Feb 15 '16 at 11:45





            @Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument

            – yairchu
            Feb 15 '16 at 11:45











            5














            There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after.






            share|improve this answer




























              5














              There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after.






              share|improve this answer


























                5












                5








                5







                There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after.






                share|improve this answer













                There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jul 9 '09 at 19:00









                Richard DunlapRichard Dunlap

                1,732914




                1,732914























                    1














                    The definition of fibonaci(n) is:



                    fibonacci (n) = fibonacci (n-1) + fibonacci (n-2)



                    The naive implementation in Haskell



                    fibonacci :: Integer -> Integer
                    fibonacci 0 = 1
                    fibonacci 1 = 1
                    fibonacci x = fibonacci (x-1) + fibonacci (x-2)


                    All formulas can be traced back to this definition, some which run very quickly, some of which run very slowly. The implementation above has O(n) = 2^n



                    In the spirit of your question, let me remove the use of lists and give you something that runs in O(n) I.e. let's not hold all the fibonaccis from 0 to n in a list.



                    If we have a triple (a tuple with three members) that looks like:



                    (n, fibonacci[n-1], fibonacci[n])



                    Remembering the initial definition, we can calculate the next triple from the last triple:



                    (n+1, fibonacci[n], fibonacci[n-1] + fibonacci[n])
                    = (n+1, fibonacci[n], fibonacci[n+1])



                    And the next triple from the last triple:
                    (n+2, fibonacci[n+1], fibonacci[n] + fibonacci[n+1])
                    = (n+1, fibonacci[n+1], fibonacci[n+2])



                    And so on...



                    n = 0 => (0,0,1) 
                    n = 1 => (1,1,1) - calculated from the previous triple
                    n = 2 => (2,1,2) - calculated from the previous triple
                    n = 3 => (3,2,3) - calculated from the previous triple
                    n = 4 => (4,3,5) - calculated from the previous triple
                    n = 5 => (5,5,8) - calculated from the previous triple


                    Let's implement this in Haskell and use self explanatory variable names:



                    nextTripleIfCurrentNIsLessThanN :: (Int, Integer, Integer) -> Int -> (Int, Integer, Integer)
                    nextTripleIfCurrentNIsLessThanN (currentN, x, y) n = if currentN < n
                    then nextTripleIfCurrentNIsLessThanN (currentN + 1, y, x + y) n
                    else (currentN, x, y)

                    thirdElementOfTriple :: (x,y,z) -> z
                    thirdElementOfTriple (x,y,z) = z

                    fibonacci :: Int -> Integer
                    fibonacci n = thirdElementOfTriple (nextTripleIfCurrentNIsLessThanN (0,0,1) n)


                    This will work in O(n) [It is mildly quadratic which shows up in large numbers. The reason for that is that adding big numbers is more costly than adding small ones. But that's a separate discussion about model of computation.]



                    fibonacci 0
                    1
                    fibonacci 1
                    1
                    fibonacci 2
                    2
                    fibonacci 3
                    3
                    fibonacci 4
                    5
                    fibonacci 5
                    8
                    fibonacci 5000
                    6276302800488957086035253108349684055478528702736457439025824448927937256811663264475883711527806250329984690249846819800648580083040107584710332687596562185073640422286799239932615797105974710857095487342820351307477141875012176874307156016229965832589137779724973854362777629878229505500260477136108363709090010421536915488632339240756987974122598603591920306874926755600361865354330444681915154695741851960071089944015319300128574107662757054790648152751366475529121877212785489665101733755898580317984402963873738187000120737824193162011399200547424034440836239726275765901190914513013217132050988064832024783370583789324109052449717186857327239783000020791777804503930439875068662687670678802914269784817022567088069496231111407908953313902398529655056082228598715882365779469902465675715699187225655878240668599547496218159297881601061923195562143932693324644219266564617042934227893371179832389642895285401263875342640468017378925921483580111278055044254198382265567395946431803304304326865077742925818757370691726168228648841319231470626





                    share|improve this answer






























                      1














                      The definition of fibonaci(n) is:



                      fibonacci (n) = fibonacci (n-1) + fibonacci (n-2)



                      The naive implementation in Haskell



                      fibonacci :: Integer -> Integer
                      fibonacci 0 = 1
                      fibonacci 1 = 1
                      fibonacci x = fibonacci (x-1) + fibonacci (x-2)


                      All formulas can be traced back to this definition, some which run very quickly, some of which run very slowly. The implementation above has O(n) = 2^n



                      In the spirit of your question, let me remove the use of lists and give you something that runs in O(n) I.e. let's not hold all the fibonaccis from 0 to n in a list.



                      If we have a triple (a tuple with three members) that looks like:



                      (n, fibonacci[n-1], fibonacci[n])



                      Remembering the initial definition, we can calculate the next triple from the last triple:



                      (n+1, fibonacci[n], fibonacci[n-1] + fibonacci[n])
                      = (n+1, fibonacci[n], fibonacci[n+1])



                      And the next triple from the last triple:
                      (n+2, fibonacci[n+1], fibonacci[n] + fibonacci[n+1])
                      = (n+1, fibonacci[n+1], fibonacci[n+2])



                      And so on...



                      n = 0 => (0,0,1) 
                      n = 1 => (1,1,1) - calculated from the previous triple
                      n = 2 => (2,1,2) - calculated from the previous triple
                      n = 3 => (3,2,3) - calculated from the previous triple
                      n = 4 => (4,3,5) - calculated from the previous triple
                      n = 5 => (5,5,8) - calculated from the previous triple


                      Let's implement this in Haskell and use self explanatory variable names:



                      nextTripleIfCurrentNIsLessThanN :: (Int, Integer, Integer) -> Int -> (Int, Integer, Integer)
                      nextTripleIfCurrentNIsLessThanN (currentN, x, y) n = if currentN < n
                      then nextTripleIfCurrentNIsLessThanN (currentN + 1, y, x + y) n
                      else (currentN, x, y)

                      thirdElementOfTriple :: (x,y,z) -> z
                      thirdElementOfTriple (x,y,z) = z

                      fibonacci :: Int -> Integer
                      fibonacci n = thirdElementOfTriple (nextTripleIfCurrentNIsLessThanN (0,0,1) n)


                      This will work in O(n) [It is mildly quadratic which shows up in large numbers. The reason for that is that adding big numbers is more costly than adding small ones. But that's a separate discussion about model of computation.]



                      fibonacci 0
                      1
                      fibonacci 1
                      1
                      fibonacci 2
                      2
                      fibonacci 3
                      3
                      fibonacci 4
                      5
                      fibonacci 5
                      8
                      fibonacci 5000
                      6276302800488957086035253108349684055478528702736457439025824448927937256811663264475883711527806250329984690249846819800648580083040107584710332687596562185073640422286799239932615797105974710857095487342820351307477141875012176874307156016229965832589137779724973854362777629878229505500260477136108363709090010421536915488632339240756987974122598603591920306874926755600361865354330444681915154695741851960071089944015319300128574107662757054790648152751366475529121877212785489665101733755898580317984402963873738187000120737824193162011399200547424034440836239726275765901190914513013217132050988064832024783370583789324109052449717186857327239783000020791777804503930439875068662687670678802914269784817022567088069496231111407908953313902398529655056082228598715882365779469902465675715699187225655878240668599547496218159297881601061923195562143932693324644219266564617042934227893371179832389642895285401263875342640468017378925921483580111278055044254198382265567395946431803304304326865077742925818757370691726168228648841319231470626





                      share|improve this answer




























                        1












                        1








                        1







                        The definition of fibonaci(n) is:



                        fibonacci (n) = fibonacci (n-1) + fibonacci (n-2)



                        The naive implementation in Haskell



                        fibonacci :: Integer -> Integer
                        fibonacci 0 = 1
                        fibonacci 1 = 1
                        fibonacci x = fibonacci (x-1) + fibonacci (x-2)


                        All formulas can be traced back to this definition, some which run very quickly, some of which run very slowly. The implementation above has O(n) = 2^n



                        In the spirit of your question, let me remove the use of lists and give you something that runs in O(n) I.e. let's not hold all the fibonaccis from 0 to n in a list.



                        If we have a triple (a tuple with three members) that looks like:



                        (n, fibonacci[n-1], fibonacci[n])



                        Remembering the initial definition, we can calculate the next triple from the last triple:



                        (n+1, fibonacci[n], fibonacci[n-1] + fibonacci[n])
                        = (n+1, fibonacci[n], fibonacci[n+1])



                        And the next triple from the last triple:
                        (n+2, fibonacci[n+1], fibonacci[n] + fibonacci[n+1])
                        = (n+1, fibonacci[n+1], fibonacci[n+2])



                        And so on...



                        n = 0 => (0,0,1) 
                        n = 1 => (1,1,1) - calculated from the previous triple
                        n = 2 => (2,1,2) - calculated from the previous triple
                        n = 3 => (3,2,3) - calculated from the previous triple
                        n = 4 => (4,3,5) - calculated from the previous triple
                        n = 5 => (5,5,8) - calculated from the previous triple


                        Let's implement this in Haskell and use self explanatory variable names:



                        nextTripleIfCurrentNIsLessThanN :: (Int, Integer, Integer) -> Int -> (Int, Integer, Integer)
                        nextTripleIfCurrentNIsLessThanN (currentN, x, y) n = if currentN < n
                        then nextTripleIfCurrentNIsLessThanN (currentN + 1, y, x + y) n
                        else (currentN, x, y)

                        thirdElementOfTriple :: (x,y,z) -> z
                        thirdElementOfTriple (x,y,z) = z

                        fibonacci :: Int -> Integer
                        fibonacci n = thirdElementOfTriple (nextTripleIfCurrentNIsLessThanN (0,0,1) n)


                        This will work in O(n) [It is mildly quadratic which shows up in large numbers. The reason for that is that adding big numbers is more costly than adding small ones. But that's a separate discussion about model of computation.]



                        fibonacci 0
                        1
                        fibonacci 1
                        1
                        fibonacci 2
                        2
                        fibonacci 3
                        3
                        fibonacci 4
                        5
                        fibonacci 5
                        8
                        fibonacci 5000
                        6276302800488957086035253108349684055478528702736457439025824448927937256811663264475883711527806250329984690249846819800648580083040107584710332687596562185073640422286799239932615797105974710857095487342820351307477141875012176874307156016229965832589137779724973854362777629878229505500260477136108363709090010421536915488632339240756987974122598603591920306874926755600361865354330444681915154695741851960071089944015319300128574107662757054790648152751366475529121877212785489665101733755898580317984402963873738187000120737824193162011399200547424034440836239726275765901190914513013217132050988064832024783370583789324109052449717186857327239783000020791777804503930439875068662687670678802914269784817022567088069496231111407908953313902398529655056082228598715882365779469902465675715699187225655878240668599547496218159297881601061923195562143932693324644219266564617042934227893371179832389642895285401263875342640468017378925921483580111278055044254198382265567395946431803304304326865077742925818757370691726168228648841319231470626





                        share|improve this answer















                        The definition of fibonaci(n) is:



                        fibonacci (n) = fibonacci (n-1) + fibonacci (n-2)



                        The naive implementation in Haskell



                        fibonacci :: Integer -> Integer
                        fibonacci 0 = 1
                        fibonacci 1 = 1
                        fibonacci x = fibonacci (x-1) + fibonacci (x-2)


                        All formulas can be traced back to this definition, some which run very quickly, some of which run very slowly. The implementation above has O(n) = 2^n



                        In the spirit of your question, let me remove the use of lists and give you something that runs in O(n) I.e. let's not hold all the fibonaccis from 0 to n in a list.



                        If we have a triple (a tuple with three members) that looks like:



                        (n, fibonacci[n-1], fibonacci[n])



                        Remembering the initial definition, we can calculate the next triple from the last triple:



                        (n+1, fibonacci[n], fibonacci[n-1] + fibonacci[n])
                        = (n+1, fibonacci[n], fibonacci[n+1])



                        And the next triple from the last triple:
                        (n+2, fibonacci[n+1], fibonacci[n] + fibonacci[n+1])
                        = (n+1, fibonacci[n+1], fibonacci[n+2])



                        And so on...



                        n = 0 => (0,0,1) 
                        n = 1 => (1,1,1) - calculated from the previous triple
                        n = 2 => (2,1,2) - calculated from the previous triple
                        n = 3 => (3,2,3) - calculated from the previous triple
                        n = 4 => (4,3,5) - calculated from the previous triple
                        n = 5 => (5,5,8) - calculated from the previous triple


                        Let's implement this in Haskell and use self explanatory variable names:



                        nextTripleIfCurrentNIsLessThanN :: (Int, Integer, Integer) -> Int -> (Int, Integer, Integer)
                        nextTripleIfCurrentNIsLessThanN (currentN, x, y) n = if currentN < n
                        then nextTripleIfCurrentNIsLessThanN (currentN + 1, y, x + y) n
                        else (currentN, x, y)

                        thirdElementOfTriple :: (x,y,z) -> z
                        thirdElementOfTriple (x,y,z) = z

                        fibonacci :: Int -> Integer
                        fibonacci n = thirdElementOfTriple (nextTripleIfCurrentNIsLessThanN (0,0,1) n)


                        This will work in O(n) [It is mildly quadratic which shows up in large numbers. The reason for that is that adding big numbers is more costly than adding small ones. But that's a separate discussion about model of computation.]



                        fibonacci 0
                        1
                        fibonacci 1
                        1
                        fibonacci 2
                        2
                        fibonacci 3
                        3
                        fibonacci 4
                        5
                        fibonacci 5
                        8
                        fibonacci 5000
                        6276302800488957086035253108349684055478528702736457439025824448927937256811663264475883711527806250329984690249846819800648580083040107584710332687596562185073640422286799239932615797105974710857095487342820351307477141875012176874307156016229965832589137779724973854362777629878229505500260477136108363709090010421536915488632339240756987974122598603591920306874926755600361865354330444681915154695741851960071089944015319300128574107662757054790648152751366475529121877212785489665101733755898580317984402963873738187000120737824193162011399200547424034440836239726275765901190914513013217132050988064832024783370583789324109052449717186857327239783000020791777804503930439875068662687670678802914269784817022567088069496231111407908953313902398529655056082228598715882365779469902465675715699187225655878240668599547496218159297881601061923195562143932693324644219266564617042934227893371179832389642895285401263875342640468017378925921483580111278055044254198382265567395946431803304304326865077742925818757370691726168228648841319231470626






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Dec 2 '17 at 12:06

























                        answered Nov 9 '17 at 15:36









                        galeaspablogaleaspablo

                        614414




                        614414























                            1














                            This implementation calculates 100,000th Fibonacci number almost instantly:



                            fib = fastFib 1 1

                            fastFib _ _ 0 = 0
                            fastFib _ _ 1 = 1
                            fastFib _ _ 2 = 1
                            fastFib a b 3 = a + b
                            fastFib a b c = fastFib (a + b) a (c - 1)





                            share|improve this answer




























                              1














                              This implementation calculates 100,000th Fibonacci number almost instantly:



                              fib = fastFib 1 1

                              fastFib _ _ 0 = 0
                              fastFib _ _ 1 = 1
                              fastFib _ _ 2 = 1
                              fastFib a b 3 = a + b
                              fastFib a b c = fastFib (a + b) a (c - 1)





                              share|improve this answer


























                                1












                                1








                                1







                                This implementation calculates 100,000th Fibonacci number almost instantly:



                                fib = fastFib 1 1

                                fastFib _ _ 0 = 0
                                fastFib _ _ 1 = 1
                                fastFib _ _ 2 = 1
                                fastFib a b 3 = a + b
                                fastFib a b c = fastFib (a + b) a (c - 1)





                                share|improve this answer













                                This implementation calculates 100,000th Fibonacci number almost instantly:



                                fib = fastFib 1 1

                                fastFib _ _ 0 = 0
                                fastFib _ _ 1 = 1
                                fastFib _ _ 2 = 1
                                fastFib a b 3 = a + b
                                fastFib a b c = fastFib (a + b) a (c - 1)






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Feb 23 at 16:27









                                Remisa YousefvandRemisa Yousefvand

                                1478




                                1478























                                    0














                                    A lazy way of generating infinite Fibonacci series can easily be achieved by unfoldr as follows;



                                    fibs :: [Integer]
                                    fibs = unfoldr ((f,s) -> Just (f,(s,f+s))) (0,1)





                                    share|improve this answer




























                                      0














                                      A lazy way of generating infinite Fibonacci series can easily be achieved by unfoldr as follows;



                                      fibs :: [Integer]
                                      fibs = unfoldr ((f,s) -> Just (f,(s,f+s))) (0,1)





                                      share|improve this answer


























                                        0












                                        0








                                        0







                                        A lazy way of generating infinite Fibonacci series can easily be achieved by unfoldr as follows;



                                        fibs :: [Integer]
                                        fibs = unfoldr ((f,s) -> Just (f,(s,f+s))) (0,1)





                                        share|improve this answer













                                        A lazy way of generating infinite Fibonacci series can easily be achieved by unfoldr as follows;



                                        fibs :: [Integer]
                                        fibs = unfoldr ((f,s) -> Just (f,(s,f+s))) (0,1)






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered May 10 '17 at 16:36









                                        ReduRedu

                                        12.9k22537




                                        12.9k22537























                                            0














                                            LOL, I love Haskell pattern matching but it is rendered useless in standard Fibonacci functions. The standard list is constructed from the right. To use pattern matching and cons, the list must be constructed from the left. Well, one consolation, at least, is this is really fast. ~O(n), it should be. A helper function is needed to reverse the infinite list (things you can only do in Haskell, joy) and this function outputs each subsequent list of the run so 'last' is also used in the helper function pipeline.



                                            f (x:y:xs) = (x+y):(x:(y:xs))


                                            The helper



                                            fib n = reverse . last . take n $ iterate f [1,0]


                                            This is a list version and, I think, it explicates how the list is constructed which is the purpose. I want to do a tuple version.



                                            Edit 3/15/2018



                                            First off, Will Ness enlightened me with the knowledge that an entire list being generated at each iteration was unnecessary and that only the last two values used were needed and that the values for the result list were the first values of each list or pair generated. It was so funny. After Will told me the values for the list were the first values of the lists, I ran it and saw the values 0,1,1,2,3,5,8,13 as each head of each list, I said WTF, did Will change my code on my PC? The values were there but how!? After a while, I realized they were there all along but I just didn't see them. ugh.
                                            Will's version of the function and helper function are:



                                            f = ((x:y:xs) -> (x+y):x:xs) -- notice, no y: put back only x+y & x


                                            and his helper function rewrite



                                            fib n = map head . take n $iterate f [0,1]


                                            I think, too, that they now can be combined:



                                            fib n = take n . map head $ iterate ((x:y:xs) -> (x+y):x:xs) [0,1]


                                            As an irrelevant aside, the function can be with tuples, too



                                            fib n = take n . map fst $ iterate ((a,b) -> (b,a+b)) (0,1)


                                            Another form, a list comprehension form, can also be written for all:



                                            fib n = take n [ fst t | t <- iterate ((a,b) -> (b,a+b)) (0,1)]


                                            These are all iterative and robust. The fastest is the map with lists at 12.23 seconds for fib 5000. The tuple comprehension was second fastest for fib 5000 at 13.58 seconds.






                                            share|improve this answer


























                                            • haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

                                              – Will Ness
                                              Mar 12 '18 at 14:20













                                            • It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

                                              – fp_mora
                                              Mar 13 '18 at 16:51











                                            • try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

                                              – Will Ness
                                              Mar 13 '18 at 17:23













                                            • want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

                                              – Will Ness
                                              Mar 13 '18 at 17:56











                                            • @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

                                              – fp_mora
                                              Mar 13 '18 at 17:57
















                                            0














                                            LOL, I love Haskell pattern matching but it is rendered useless in standard Fibonacci functions. The standard list is constructed from the right. To use pattern matching and cons, the list must be constructed from the left. Well, one consolation, at least, is this is really fast. ~O(n), it should be. A helper function is needed to reverse the infinite list (things you can only do in Haskell, joy) and this function outputs each subsequent list of the run so 'last' is also used in the helper function pipeline.



                                            f (x:y:xs) = (x+y):(x:(y:xs))


                                            The helper



                                            fib n = reverse . last . take n $ iterate f [1,0]


                                            This is a list version and, I think, it explicates how the list is constructed which is the purpose. I want to do a tuple version.



                                            Edit 3/15/2018



                                            First off, Will Ness enlightened me with the knowledge that an entire list being generated at each iteration was unnecessary and that only the last two values used were needed and that the values for the result list were the first values of each list or pair generated. It was so funny. After Will told me the values for the list were the first values of the lists, I ran it and saw the values 0,1,1,2,3,5,8,13 as each head of each list, I said WTF, did Will change my code on my PC? The values were there but how!? After a while, I realized they were there all along but I just didn't see them. ugh.
                                            Will's version of the function and helper function are:



                                            f = ((x:y:xs) -> (x+y):x:xs) -- notice, no y: put back only x+y & x


                                            and his helper function rewrite



                                            fib n = map head . take n $iterate f [0,1]


                                            I think, too, that they now can be combined:



                                            fib n = take n . map head $ iterate ((x:y:xs) -> (x+y):x:xs) [0,1]


                                            As an irrelevant aside, the function can be with tuples, too



                                            fib n = take n . map fst $ iterate ((a,b) -> (b,a+b)) (0,1)


                                            Another form, a list comprehension form, can also be written for all:



                                            fib n = take n [ fst t | t <- iterate ((a,b) -> (b,a+b)) (0,1)]


                                            These are all iterative and robust. The fastest is the map with lists at 12.23 seconds for fib 5000. The tuple comprehension was second fastest for fib 5000 at 13.58 seconds.






                                            share|improve this answer


























                                            • haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

                                              – Will Ness
                                              Mar 12 '18 at 14:20













                                            • It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

                                              – fp_mora
                                              Mar 13 '18 at 16:51











                                            • try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

                                              – Will Ness
                                              Mar 13 '18 at 17:23













                                            • want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

                                              – Will Ness
                                              Mar 13 '18 at 17:56











                                            • @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

                                              – fp_mora
                                              Mar 13 '18 at 17:57














                                            0












                                            0








                                            0







                                            LOL, I love Haskell pattern matching but it is rendered useless in standard Fibonacci functions. The standard list is constructed from the right. To use pattern matching and cons, the list must be constructed from the left. Well, one consolation, at least, is this is really fast. ~O(n), it should be. A helper function is needed to reverse the infinite list (things you can only do in Haskell, joy) and this function outputs each subsequent list of the run so 'last' is also used in the helper function pipeline.



                                            f (x:y:xs) = (x+y):(x:(y:xs))


                                            The helper



                                            fib n = reverse . last . take n $ iterate f [1,0]


                                            This is a list version and, I think, it explicates how the list is constructed which is the purpose. I want to do a tuple version.



                                            Edit 3/15/2018



                                            First off, Will Ness enlightened me with the knowledge that an entire list being generated at each iteration was unnecessary and that only the last two values used were needed and that the values for the result list were the first values of each list or pair generated. It was so funny. After Will told me the values for the list were the first values of the lists, I ran it and saw the values 0,1,1,2,3,5,8,13 as each head of each list, I said WTF, did Will change my code on my PC? The values were there but how!? After a while, I realized they were there all along but I just didn't see them. ugh.
                                            Will's version of the function and helper function are:



                                            f = ((x:y:xs) -> (x+y):x:xs) -- notice, no y: put back only x+y & x


                                            and his helper function rewrite



                                            fib n = map head . take n $iterate f [0,1]


                                            I think, too, that they now can be combined:



                                            fib n = take n . map head $ iterate ((x:y:xs) -> (x+y):x:xs) [0,1]


                                            As an irrelevant aside, the function can be with tuples, too



                                            fib n = take n . map fst $ iterate ((a,b) -> (b,a+b)) (0,1)


                                            Another form, a list comprehension form, can also be written for all:



                                            fib n = take n [ fst t | t <- iterate ((a,b) -> (b,a+b)) (0,1)]


                                            These are all iterative and robust. The fastest is the map with lists at 12.23 seconds for fib 5000. The tuple comprehension was second fastest for fib 5000 at 13.58 seconds.






                                            share|improve this answer















                                            LOL, I love Haskell pattern matching but it is rendered useless in standard Fibonacci functions. The standard list is constructed from the right. To use pattern matching and cons, the list must be constructed from the left. Well, one consolation, at least, is this is really fast. ~O(n), it should be. A helper function is needed to reverse the infinite list (things you can only do in Haskell, joy) and this function outputs each subsequent list of the run so 'last' is also used in the helper function pipeline.



                                            f (x:y:xs) = (x+y):(x:(y:xs))


                                            The helper



                                            fib n = reverse . last . take n $ iterate f [1,0]


                                            This is a list version and, I think, it explicates how the list is constructed which is the purpose. I want to do a tuple version.



                                            Edit 3/15/2018



                                            First off, Will Ness enlightened me with the knowledge that an entire list being generated at each iteration was unnecessary and that only the last two values used were needed and that the values for the result list were the first values of each list or pair generated. It was so funny. After Will told me the values for the list were the first values of the lists, I ran it and saw the values 0,1,1,2,3,5,8,13 as each head of each list, I said WTF, did Will change my code on my PC? The values were there but how!? After a while, I realized they were there all along but I just didn't see them. ugh.
                                            Will's version of the function and helper function are:



                                            f = ((x:y:xs) -> (x+y):x:xs) -- notice, no y: put back only x+y & x


                                            and his helper function rewrite



                                            fib n = map head . take n $iterate f [0,1]


                                            I think, too, that they now can be combined:



                                            fib n = take n . map head $ iterate ((x:y:xs) -> (x+y):x:xs) [0,1]


                                            As an irrelevant aside, the function can be with tuples, too



                                            fib n = take n . map fst $ iterate ((a,b) -> (b,a+b)) (0,1)


                                            Another form, a list comprehension form, can also be written for all:



                                            fib n = take n [ fst t | t <- iterate ((a,b) -> (b,a+b)) (0,1)]


                                            These are all iterative and robust. The fastest is the map with lists at 12.23 seconds for fib 5000. The tuple comprehension was second fastest for fib 5000 at 13.58 seconds.







                                            share|improve this answer














                                            share|improve this answer



                                            share|improve this answer








                                            edited Mar 18 '18 at 0:43

























                                            answered Mar 11 '18 at 19:20









                                            fp_morafp_mora

                                            43145




                                            43145













                                            • haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

                                              – Will Ness
                                              Mar 12 '18 at 14:20













                                            • It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

                                              – fp_mora
                                              Mar 13 '18 at 16:51











                                            • try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

                                              – Will Ness
                                              Mar 13 '18 at 17:23













                                            • want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

                                              – Will Ness
                                              Mar 13 '18 at 17:56











                                            • @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

                                              – fp_mora
                                              Mar 13 '18 at 17:57



















                                            • haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

                                              – Will Ness
                                              Mar 12 '18 at 14:20













                                            • It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

                                              – fp_mora
                                              Mar 13 '18 at 16:51











                                            • try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

                                              – Will Ness
                                              Mar 13 '18 at 17:23













                                            • want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

                                              – Will Ness
                                              Mar 13 '18 at 17:56











                                            • @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

                                              – fp_mora
                                              Mar 13 '18 at 17:57

















                                            haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

                                            – Will Ness
                                            Mar 12 '18 at 14:20







                                            haskell lists can be constructed from the top (left) though just as easily, with guarded recursion (i.e. thanks to the laziness; e.g. this answer). last . take n is just (!! (n-1)). with your fib, fib n doesn't help to find fib (n+1) as much as we'd want. just define instead fibs = map head $ iterate f [1,0] and then fib n = fibs !! n. Now we discover that it creates a whole list on each step but uses only 2 of its head elements, so we change it to fibs = map fst $ iterate g (1,0) with f correspondingly changed, into g. voila.

                                            – Will Ness
                                            Mar 12 '18 at 14:20















                                            It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

                                            – fp_mora
                                            Mar 13 '18 at 16:51





                                            It takes real vision to see that the head of each list generated were the numbers desired. I lack that vision. Thank you so very much, This lesson extends well beyond this problem and your piercing insight into it. That said, I take map fst $ iterate g (1,0) as delightful humor. The tuple version is indeed to replace f Also in "fibs = map head $ iterate f [1,0]" using [0,1] as a parameter results in 0 as the head of the output list of "take n $ map head $ iterate f [0,1]' I have no working concept of the tuple version, yet and yes, laziness in a language is better than ice cream. Almost.

                                            – fp_mora
                                            Mar 13 '18 at 16:51













                                            try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

                                            – Will Ness
                                            Mar 13 '18 at 17:23







                                            try mapM_ print $ take 15 $ iterate f [1,0]. Now change f to f (x:y:xs) = (x+y):(x:xs) and try that mapM_ ... line again and compare the outputs.

                                            – Will Ness
                                            Mar 13 '18 at 17:23















                                            want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

                                            – Will Ness
                                            Mar 13 '18 at 17:56





                                            want to be blown away by laziness, try ps n = q where q = scanl (\) [2..n] [[p,p+p..n] | p <- map head q], then try map head $ ps 100 or map head $ ps 555. you might need to import Data.List to get the (\), first. To see what's going on there, try mapM_ print $ ps 100.

                                            – Will Ness
                                            Mar 13 '18 at 17:56













                                            @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

                                            – fp_mora
                                            Mar 13 '18 at 17:57





                                            @Will Ness is a wizard He improved my sorry code with "f (x:y:xs) = (x+y):(x:xs)" which is much cleaner. His reworking of the helper function is "map head $ take 24 $ iterate f [0,1]" which is also very much cleaner Haskell's laziness prevents any performance penalty for expressive clarity. I am a Haskell neophyte so cherish this site & wonderful people B/c of Will Ness, I just used a monad & soon will get to explore the '\' operator & scanl which I also have never done Will Ness, what I was really looking for was f . f . f ... f (x) Using the Y combinator It should be sweet

                                            – fp_mora
                                            Mar 13 '18 at 17:57











                                            -1














                                            using iterate



                                            fibonaci = map fst (iterate f (0,1)) where f (x,y) = (y,x+y)


                                            using



                                            take 10 fibonaci

                                            [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]





                                            share|improve this answer






























                                              -1














                                              using iterate



                                              fibonaci = map fst (iterate f (0,1)) where f (x,y) = (y,x+y)


                                              using



                                              take 10 fibonaci

                                              [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]





                                              share|improve this answer




























                                                -1












                                                -1








                                                -1







                                                using iterate



                                                fibonaci = map fst (iterate f (0,1)) where f (x,y) = (y,x+y)


                                                using



                                                take 10 fibonaci

                                                [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]





                                                share|improve this answer















                                                using iterate



                                                fibonaci = map fst (iterate f (0,1)) where f (x,y) = (y,x+y)


                                                using



                                                take 10 fibonaci

                                                [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]






                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Apr 20 '14 at 1:13

























                                                answered Apr 19 '14 at 13:50









                                                jmejiajmejia

                                                11




                                                11






























                                                    draft saved

                                                    draft discarded




















































                                                    Thanks for contributing an answer to Stack Overflow!


                                                    • Please be sure to answer the question. Provide details and share your research!

                                                    But avoid



                                                    • Asking for help, clarification, or responding to other answers.

                                                    • Making statements based on opinion; back them up with references or personal experience.


                                                    To learn more, see our tips on writing great answers.




                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function () {
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1105765%2fgenerating-fibonacci-numbers-in-haskell%23new-answer', 'question_page');
                                                    }
                                                    );

                                                    Post as a guest















                                                    Required, but never shown





















































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown

































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown







                                                    Popular posts from this blog

                                                    Wiesbaden

                                                    Marschland

                                                    Dieringhausen