Get each fibbonacci value in haskell

86 views Asked by At

I'm learning haskell and I have the following code:

fib a b =
  a : fib b (a + b)

findFibSum =
  sum [x | x <- fib 1 2, mod x 2 == 0 && x < 100]

If I run findFibSum nothing happens, it just sits there. Shouldn't fib be evaluated and return each item? I'm guessing this has something to do with lazy evaluation.

If I call take first and make findFibSum accept the taken list like:

findFibSum $ take 100 $ fib 1 2

it works instead. How do I make it so that I can retrieve and check each item instead? I can probably get away by taking by batch using take but I'd like to understand this first.

UPDATE

Thanks to @amalloy i finally got it working with:

findFibSum xs =
  sum [x | x <- takeWhile (<4000000) xs, mod x 2 == 0]

takeWhile ensures that it'll stop retrieving value from fib once it gets >= 4m.

1

There are 1 answers

0
amalloy On BEST ANSWER

Consider the simpler problem of summing the first 100 positive integers:

sum [x | x <- [1,2..], x <= 100]

This doesn't work either. As a human, you know that once x <= 100 returns False, it will never return True again, because x is getting larger. But Haskell doesn't know that! So this list comprehension produces the first 100 integers, then tries 101 and finds it doesn't work, then tries 102 and finds it doesn't work...there's no point at which sum can be sure there are no more elements in the list, so it can never return a number for you.

Your list comprehension over fib 1 2 has the same problem. You can resolve it by calling take or takeWhile separately, instead of using a guard on each element, as you demonstrate in your question.