I have been trying to make a infinite fibonacci list producing function that can take first 2 values as parameters.
Without specifying the first two values it is possible like this
fib = 1 : 1 : zipWith (+) fib (tail fib)
Suppose I wanted to start the fibonacci sequence with 5 and 6 instead of 1,1 or 0,1 then I will have to change the above code. But when trying to make a lazy list generator in which I can specify the first 2 values of fibonacci sequence I am stumped. I came up with this but that didn't work.
fib a b = a : b : zipWith (+) fib (tail fib)
The problem is obvious. I am trying to convert the use of list in the hard-coded one. How can I solve that?
How about
fib a b = fibs where fibs = a : b : zipWith (+) fibs (tail fibs)
? Use the same method, but with your parameters in scope.
I should add that, in case you are tempted by
fib a b = a : b : zipWith (+) (fib a b) (tail (fib a b)) -- worth trying?
the where fibs version ensures that only one infinite stream is generated. The latter risks generating a fresh stream for each recursive invocation of fib. The compiler might be clever enough to spot the common subexpression, but it is not wise to rely on such luck. Try both versions in ghci and see how long it takes to compute the 1000th element.
The simplest way to do that is:
fib a b = a: fib b (a+b)
This stems from the inductive definition of the Fibonacci series: suppose we have a function that can produce a stream of Fibonacci numbers from Fi onwards, given Fi and Fi+1. What could that function look like? Well, Fi is given, and the rest of the stream can be computed using this function to produce a stream of Fibonacci numbers from Fi+1 onwards, if we can provide Fi+1 and Fi+2. Fi+1 is given, so we only need to work out Fi+2. The definition of series gives us Fi+2=Fi+Fi+1, so, there.
Related
In Haskell, the canonical zipWith implementation of the fibonacci function is :
fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
I have difficulty analysing the time complexity of this (fibs !! n).
Trying to write it on paper, at first i thought it was exponential.
Then O(n^2) , but I have no clue how it happens to be linear.
Why i think it is linear : https://wiki.haskell.org/The_Fibonacci_sequence#Canonical_zipWith_implementation
Also, i wrote another code :
fibs :: [Integer]
fibs = inc (0,1) where inc (a,b) = a : inc (b,a+b)
This, I believe is clearly O(n). But using the :set +s option in ghci, I see that the zipWith implementation clearly beats mine.
Note: I know that it takes O(n) time for addition of nth and (n-1)th fibonacci number. Thus while testing, i made the base case, i.e. the first two elements 0 : 0 .
Time complexities are mentioned using the same assumption.
It would be great if i could get some help with tracing these function calls. I'm interested to know which function was called when and maybe print something to let me know what is going on.
My unsuccessful attempt at this :
zipWith' = trace ("Called zipWith") (zipWith)
add' a b = trace (show a ++ " + " ++ (show b)) (add a b)
fibs = trace ("Called fibs") (1 : 1 : zipWith (+) fibs (tail fibs))
This does not work. The statements are printed exactly one.
Except for add' which works fine, surprisingly.
I wish to know how many times and in what order these functions were called.
I believe your version is slow primarily because you're running it without optimization, and so you end up building a bunch of unnecessary tuples. The partially hand-optimized (and more idiomatic) version would be
fibs = inc 0 1
where
inc a b = a : inc b (a+b)
Let's look at the classic:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
The initial representation in memory looks very much like that. It's a list cons pointing to the number 1 and a second list cons pointing to the number 1 and a thunk representing zipWith (+) fibs (tail fibs). What happens when that thunk is forced? Well zipWith needs to inspect both of it's list arguments. It does so, and, seeing that they're not null, produces a list cons pointing to a thunk representing 1+1 and a thunk representing zipWith (+) fibs' (tail fibs'), where fibs' is a pointer to the second cons in the sequence. There's no need to evaluate fibs again for each of the zipWith arguments or anything like that.
I have the following, oft-quoted code for calculating the nth Fibonacci number in Haskell:
fibonacci :: Int -> Integer
fibonacci = (map fib [0..] !!)
where fib 0 = 0
fib 1 = 1
fib n = fibonacci (n-2) + fibonacci (n-1)
Using this, I can do calls such as:
ghci> fibonacci 1000
and receive an almost instantaneous answer.
However, if I modify the above code so that it's not in pointfree style, i.e.
fibonacci :: Int -> Integer
fibonacci x = (map fib [0..] !!) x
where fib 0 = 0
fib 1 = 1
fib n = fibonacci (n-2) + fibonacci (n-1)
it is substantially slower. To the extent that a call such as
ghci> fibonacci 1000
hangs.
My understanding was that the above two pieces of code were equivalent, but GHCi begs to differ. Does anyone have an explanation for this behaviour?
To observe the difference, you should probably look at Core. My guess that this boils down to comparing (roughly)
let f = map fib [0..] in \x -> f !! x
to
\x -> let f = map fib [0..] in f !! x
The latter will recompute f from scratch on every invocation. The former does not, effectively caching the same f for each invocation.
It happens that in this specific case, GHC was able to optimize the second into the first, once optimization is enabled.
Note however that GHC does not always perform this transformation, since this is not always an optimization. The cache used by the first is kept in memory forever. This might lead to a waste of memory, depending on the function at hand.
I tried to find it but struck out. I think I have it on my PC at home.
What I read was that functions using fixed point were inherently faster.
There are other reasons for using fixed point. I encountered one in writing this iterative Fibonacci function. I wanted to see how an iterative version would perform then I realized I had no ready way to measure. I am a Haskell neophyte. But here is an iterative version for someone to test.
I could not get this to define unless I used the dot after the first last function.
I could not reduce it further. the [0,1] parameter is fixed and not to be supplied as a parameter value.
Prelude> fib = last . flip take (iterate (\ls -> ls ++ [last ls + last (init ls)]) [0,1])
Prelude> fib 25
[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025]
I'm playing around with the language to start learning and I am puzzled beyond my wits about how a recursive definition works.
For example, let's take the sequence of the Triangular numbers (TN n = sum [1..n])
The solution provided was:
triangularNumbers = scanl1 (+) [1..]
So far, so good.
But the solution I did come up with was:
triangularNumbers = zipWith (+) [1..] $ 0 : triangularNumbers
Which is also correct.
Now my question is: how does this translate to a lower level implementation? What happens exactly behind the scene when such a recursive definition is met?
Here is a simple recursive function that gives you the nth Triangular number:
triag 0 = 0
triag n = n + triag (n-1)
Your solution triag' = zipWith (+) [1..] $ 0 : triag' is something more fancy: It's corecursive (click, click). Instead of calculating the nth number by reducing it to the value of smaller inputs, you define the whole infinite sequence of triangular numbers by recursively specifying the next value, given an initial segment.
How does Haskell handle such corecursion? When it encounters your definition, no calculation is actually performed, it is deferred until results are needed for further computations. When you access a particular element of your list triag', Haskell starts computing the elements of the list based on the definition, up to the element that gets accessed. For more detail, I found this article on lazy evaluation helpful. In summary, lazy evaluation is great to have, unless you need to predict memory usage.
Here is a similar SO question, with a step-by step explanation of the evaluation of fibs = 0 : 1 : zipWith (+) fibs (tail fibs), a corecursive definition of the Fibonacci sequence.
I've been trying to do the 2nd Project Euler problem in haskell but I've been getting: Occurs check: cannot construct the infinite type: a = [a]
fibonacci 0 _ = 0
fibonacci 1 _ = 1
fibonacci x xs = (xs!!(x-2)) + (xs!!(x-1))
fibonaccisLessThan = takeWhile(<40) $ foldr fibonacci [] [0..]
sumOfEvenFibonaccis = sum $ filter even $ fibonaccisLessThan
main = putStrLn $ show $ sumOfEvenFibonaccis
Can someone tell me why?
Think about lines one to five. What do you want to achieve? You want to get a lazy list of Fibonaccis. But your approach is very strange. I don't see through your code, but I think I have an idea about what you try to do. Try to give your functions type-signatures, then you will see quickly, what's going wrong.
Here is a shorter way:
Think of short cutting your approach. Let's try to define a lazy list of Fibonacci numbers:
fibs = undefined
So, what now? The first thing we know, is that the first two elements are 0 and 1:
fibs = 0 : 1 : undefined
And the rest? It is fibs added with a shifted version of fibs. Look at this. zipWith f combines a list with another list using a function f:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
And here we are. That's all.
The reason for your error message is that the function fibonacci returns a number, nevertheless, you use it at line 5 as if it would return a list of that same kind of number.
This causes the type checker to try to unify a type "a" with the type "[a]" and this gives the occurs check error.
Think about it: where in your program is the list actually constructed? You know, there should be a : operator applied somewhere, directly or indirectly, but it isn't. Therefore, in your program, the list of fibonacci numbers is entirely fictional.
Some general advice: If you get a strange type error, make sure you have type signatures on all top level definitions. This ensures that your type error will be reported in the right definition.
That said, your fibonacci definition is weird.
Let us start by first noticing that fibonacci has type Int -> [Int] -> Int, and that foldr has type (a -> b -> b) -> b -> [a] -> b, so we can't give fibonacci to foldr since we can't unify a-> b-> b with Int -> [Int] -> Int. This is where the error message comes from.
To fix it we have to change the fibonacci function. fibonacci = 0 : 1 : zipWith (+) fibonacci (tail fibonacci) is the classic haskell way of doing it, for more ways take a look at this haskellwiki page. Then all you have to do is:
sumOfEvenLessThen n = sum . filter even . takeWhile (<n)
main = print $ sumOfEvenLessThen 40 fibonacci
The other answers already point out where the error comes from, and show the very compact and elegant "standard" definition of Fibonacci numbers in Haskell. Here is another way to define it, which might be more beginner friendly:
fibs = map fst $ iterate next (0,1) where
next (x,y) = (y,x+y)
The idea is to keep track not only of the last, but of the last two Fibonacci numbers, which can be done using pairs. With this trick it's very easy to define the recursive relationship.
We start with the argument (0,1) and generate a list from this start value using the next function over ond over again: [(0,1),(1,1),(1,2),(2,3),(3,5)...]. Then the only thing left to do is to "throw away" the second argument of the pairs, which is done by map fst $ ....
[Update]
Another nice definition (working similar like the zipWith-Version) is:
fibs = 0 : scanl (+) 1 fibs
I'm using project Euler to teach myself Haskell, and I'm having some trouble reasoning about how my code is being executed by haskell. The second problem has me computing the sum of all even Fibonacci numbers up to 4 million. My script looks like this:
fibs :: [Integer]
fibs = 1 : 2 : [ a+b | (a,b) <- zip fibs (tail fibs)]
evens :: Integer -> Integer -> Integer
evens x sum | (even x) = x + sum
| otherwise = sum
main = do
print (foldr evens 0 (take 4000000 fibs))
Hugs gives the error "Garbage collection fails to reclaim sufficient space", which I assume means that the list entries are not released as they are consumed by foldr.
What do I need to do to fix this? I tried writing a tail-recursive (I think) version that used accumulators, but couldn't get that to work either.
Firstly, you shouldn't use hugs. It is a toy for teaching purposes only.
GHC, however, is a fast, multicore-ready optimizing compiler for Haskell. Get it here. In particular, it does strictness analysis, and compiles to native code.
The main thing that stands out about your code is the use of foldr on a very large list. Probably you want a tail recursive loop. Like so:
import Data.List
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
evens x sum | even x = x + sum
| otherwise = sum
-- sum of even fibs in first 4M fibs
main = print (foldl' evens 0 (take 4000000 fibs))
Besides all this, the first 4M even fibs will use a fair amount of space, so it'll take a while.
Here's the sum of the first 400k even fibs, to save you some time (21s). :-)
A number of observations / hints:
the x + sums from even aren't getting evaluated until the very end
You're taking the first 4,000,000 fibs, not the fibs up to 4,000,000
There is an easier way to do this
Edit in response to comment
I'm not going to tell you what the easier way is, since that's the fun of Project Euler problems. But I will ask you a bunch of questions:
How many even fibs can you have in a row?
How long can you go without an even fib?
If you sum up all the even fibs and all the odd fibs (do this by hand), what do you notice about the sums?
You understood the problem wrong. The actual problem wants you to sum all the even Fibonacci numbers such that the Fibonacci number itself doesn't exceed 4 million (which happens to be only the first 33 Fibonacci numbers).
You are evaluating four million elements of fibs. Those numbers grow exponentially. I don't know how many bytes are required to represent the millionth Fibonacci number; just the one-thousandth Fibonacci number has 211 decimal digits, so that's going to take 22 32-bit words just to hold the digits, never mind whatever overhead gmp imposes. And these grow exponentially.
Exercise: calculuate the amount of memory needed to hold four million Fibonacci numbers.
have a look at the Prelude functions takeWhile, filter, even, and sum
takeWhile (<40) [0..]
filter even $ takeWhile (<40) [0..]
put 'em together:
ans = sum $ filter even $ takeWhile (< 4* 10^6) fibs