Haskell: Improving my tail-recursive fibonacci implementation - haskell

I have come up with the following tail-recursive fibonacci generator that works:
let {
fibo :: Integral x => [x]->x->x->x->[x]
fibo l x y 0 = l
fibo l x y n = fibo (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
}
Pardon me for the whole implementation put in one line because i am using the GHCi and haven't quite learnt how to put this in a file and run (i am yet to reach there). What i want to know is how this call:
fibo [0, 1] 0 1 5
can be improved. I do not want to pass the initial list with 0 and 1 and then pass 0 and 1 again with the limit. I believe that the implementation can be changed. What changes can be done?

Your algorithm is tail-recursive, but it looks like it has other drawbacks, namely 1) you are building the result list by appending to the end of it, and 2) it's not lazy.
For 1), note that when you append two lists a ++ b, you essentially have to reallocate a. In your case a is the growing list of fibonacci numbers and b are the next two terms. So each iteration reallocates the fibonacci numbers that have already been computed and adds on two more elements which will result in quadratic running time. It would be more efficient to prepend b to the front of a. You'll be producing the fibonacci numbers in reverse, but the running time will be linear. You can then reverse the list at the end if you want the sequence in ascending order.
Note that building the list in reverse order allows you to easily get at the last two terms of the sequence by using Code-Guru's pattern-matching idea.
For 2), note that you can't get the first element of the list until the entire computation has completed. Compare with the following lazy generation of the sequence:
fibs = 0 : (go 0 1)
where go a b = b : go b (a+b)
Even though it looks like the recursion never stops, fibs is only evaluated for as much as is needed. For example, fibs !! 3 only calls go a couple of times.

I'm not going to go to the algorithm itself, but here's some advice on how to structure your recursive functions.
First, here's how you would format your code in a separate file
fibo :: Integral x => [x]->x->x->x->[x]
fibo l x y 0 = l
fibo l x y n = fibo (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
If you save this as fibo.hs, then you can start GHCi with
ghci fibo.hs
to load the file at start. You can also load the file after starting GHCi with the command
:l fibo.hs
(assumming you start GHCi in the same directory where you saved fibo.hs)
Another nice feature is that now when you edit the file, you can reload all your changes by simply entering
:r
in the GHCi prompt.
Now, to get rid of the extra parameters, the usual pattern in Haskell is to refactor the recursive part to its own helper function and have the main function as an entry point that only takes the necessary parameters. For example,
fibo :: Integral x => x -> [x]
fibo n = fiboHelper [0,1] 0 1 n
fiboHelper :: Integral x => [x]->x->x->x->[x]
fiboHelper l x y 0 = l
fiboHelper l x y n = fiboHelper (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
Now you can call fibo simply with
> fibo 3
[0,1,1,2,3,5,8,13]
Also, a helper function like this that is not useful by itself is usually hidden inside the main function as an inner function using let or where.
fibo :: Integral x => x -> [x]
fibo n = fiboHelper [0,1] 0 1 n where
fiboHelper l x y 0 = l
fiboHelper l x y n = fiboHelper (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
An inner function like this is usually given a shorter name, because the context makes its purpose clear, so we could change the name to e.g. fibo'.
go is another commonly used name for a recursive helper function.

Just for the record: The "usual" definition for a list of Fibonacci numbers is:
fibo = 0 : scanl (+) 1 fibo

Related

Why does my function not work with an infinite list?

I'm trying to learn haskell and implemented a function conseq that would return a list of consecutive elements of size n.
conseq :: Int -> [Int] -> [[Int]]
conseq n x
| n == length(x) = [x]
| n > length(x) = [x]
| otherwise = [take n x] ++ (conseq n (drop 1 x))
This works correctly.
> take 5 $ conseq 2 [1..10]
[[1,2],[2,3],[3,4],[4,5],[5,6]]
However, if I pass [1..] instead of [1..10], the program gets stuck in an infinite loop.
As I understood it, haskell has lazy evaluation so I should still be able to get the same result right? Is it length? Shouldn't the first two conditions evaluate to false as soon as the length becomes greater than n?
What did I misunderstand?
One of the main reasons why using length is not a good idea is because when it has to be evaluated on an infinite list, it will get stuck in an infinite loop.
The good news is however, we don't need length. It would also make the time complexity worse. We can work with two enumerators, one is n-1 places ahead of the other. If this enumerator reaches the end of the list, then we know that the first enumerator still has n-1 elements, and thus we can stop yielding values:
conseq :: Int -> [a] -> [[a]]
conseq n ys = go (drop (n-1) ys) ys
where go [] _ = []
go (_:as) ba#(~(_:bs)) = take n ba : go as bs
This gives us thus:
Prelude> conseq 3 [1 ..]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8,9],[8,9,10],[9,10,11],[10,11,12],[11,12,13],[12,13,14],[13,14,15],[14,15,16],[15,16,17],[16,17,18],[17,18,19],[18,19,20],[19,20,21],[20,21,22],[21,22,23],[22,23,24],[23,24,25],[24,25,26],[25,26,27],…
Prelude> conseq 3 [1 .. 4]
[[1,2,3],[2,3,4]]
The first thing your function does is calculate length(x), so it knows whether it should return [x], [x], or [take n x] ++ (conseq n (drop 1 x))
length counts the number of elements in the list - all the elements. If you ask for the length of an infinite list, it never finishes counting.

ruby while loop translated to haskell

I've just started learning a bit of Haskell and functional programming, but I find it very difficult getting a hang of it :)
I am trying to translate a small piece of ruby code to Haskell (because I like the concept functional programming and Haskell proposes and even more because I come from a mathematics field and Haskell seems very mathematical):
class Integer
def factorial
f = 1; for i in 1..self; f *= i; end; f
end
end
boundary = 1000
m = 0
# Brown Numbers - pair of integers (m,n) where n factorial is equal with square root of m
while m <= boundary
n = 0
while n <= boundary
puts "(#{m},#{n})" if ((n.factorial + 1) == (m ** 2))
n += 1
end
m += 1
end
I could only figure out how to do factorials:
let factorial n = product [1..n]
I cannot figure out how to do the while loops or equivalent in Haskell, even though I found some examples that were far to confusing for me.
The idea is that the loops start from 0 (or 1) and continue (with an increment of 1) until it reaches a boundary (in my code is 1000). The reason there is a boundary is because I was thinking of starting parallel tasks that do the same operation but on different intervals so the results that I expect are returned faster (one operation would be done on 1 to 10000, another on 10000 to 100000, etc.).
I would really appreciate it if anyone could help out with this :)
Try this:
let results = [(x,y) | x <- [1..1000], y <- [1..1000] ,1 + fac x == y*y]
where fac n = product [1..n]
This is a list comprehension. More on that here.
To map it to your Ruby code,
The nested loops in m and n are replaced with x and y. Basically there is iteration over the values of x and y in the specified ranges (1 to 1000 inclusive in this case).
The check at the end is your filter condition for getting Brown numbers.
where allows us to create a helper function to calculate the factorial.
Note that instead of a separate function, we could have computed the factorial in place, like so:
(1 + product[1..x]) == y * y
Ultimately, the (x,y) on the left side means that it returns a list of tuples (x,y) which are your Brown numbers.
OK, this should work in your .hs file:
results :: [(Integer, Integer)] --Use instead of `Int` to fix overflow issue
results = [(x,y) | x <- [1..1000], y <- [1..1000] , fac x == y*y]
where fac n = product [1..n]
To add to shree.pat18's answer, maybe an exercise you could try is to translate the Haskell solution back into Ruby. It should be possible, because Ruby has ranges, Enumerator::Lazy and Enumerable#flat_map. The following rewritten Haskell solution should perhaps help:
import Data.List (concatMap)
results :: [(Integer, Integer)]
results = concatMap (\x -> concatMap (\y -> test x y) [1..1000]) [1..1000]
where test x y = if fac x == y*y then [(x,y)] else []
fac n = product [1..n]
Note that Haskell concatMap is more or less the same as Ruby Enumerable#flat_map.

Setting upper limit to the input set according to the output function

I'm currently stuck on setting upper limits in list comprehensions.
What I'm trying to do is to find all Fibonacci numbers below one million.
For this I had designed a rather simple recursive Fibonacci function
fib :: Int -> Integer
fib n
n == 0 = 0
n == 1 = 1
otherwise = fib (n-1) + fib (n-2)
The thing where I'm stuck on is defining the one million part. What I've got now is:
[ fib x | x <- [0..35], fib x < 1000000 ]
This because I know that the 35th number in the Fibonacci sequence is a high enough number.
However, what I'd like to have is to find that limit via a function and set it that way.
[ fib x | x <- [0..], fib x < 1000000 ]
This does give me the numbers, but it simply doesn't stop. It results in Haskell trying to find Fibonacci numbers below one million further in the sequence, which is rather fruitless.
Could anyone help me out with this? It'd be much appreciated!
The check fib x < 1000000 in the list comprehension filters away the fib x values that are less than 1000000; but the list comprehension has no way of knowing that greater values of x imply greater value of fib x and hence must continue until all x have been checked.
Use takeWhile instead:
takeWhile (< 1000000) [ fib x | x <- [0..35]]
A list comprehension is guaranteed to look at every element of the list. You want takeWhile :: (a -> Bool) -> [a] -> [a]. With it, your list is simply takeWhile (< 1000000) $ map fib [1..]. The takeWhile function simply returns the leading portion of the list which satisfies the given predicate; there's also a similar dropWhile function which drops the leading portion of the list which satisfies the given predicate, as well as span :: (a -> Bool) -> [a] -> ([a], [a]), which is just (takeWhile p xs, dropWhile p xs), and the similar break, which breaks the list in two when the predicate is true (and is equivalent to span (not . p). Thus, for instance:
takeWhile (< 3) [1,2,3,4,5,4,3,2,1] == [1,2]
dropWhile (< 3) [1,2,3,4,5,4,3,2,1] == [3,4,5,4,3,2,1]
span (< 3) [1,2,3,4,5,4,3,2,1] == ([1,2],[3,4,5,4,3,2,1])
break (> 3) [1,2,3,4,5,4,3,2,1] == ([1,2,3],[4,5,4,3,2,1])
It should be mentioned that for such a task the "canonical" (and faster) way is to define the numbers as an infinite stream, e.g.
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
takeWhile (<100) fibs
--[0,1,1,2,3,5,8,13,21,34,55,89]
The recursive definition may look scary (or even "magic") at first, but if you "think lazy", it will make sense.
A "loopy" (and in a sense more "imperative") way to define such an infinite list is:
fibs = map fst $ iterate (\(a,b) -> (b,a+b)) (0,1)
[Edit]
For an efficient direct calculation (without infinite list) you can use matrix multiplication:
fib n = second $ (0,1,1,1) ** n where
p ** 0 = (1,0,0,1)
p ** 1 = p
p ** n | even n = (p `x` p) ** (n `div` 2)
| otherwise = p `x` (p ** (n-1))
(a,b,c,d) `x` (q,r,s,t) = (a*q+b*s, a*r+b*t,c*q+d*s,c*r+d*t)
second (_,f,_,_) = f
(That was really fun to write, but I'm always grateful for suggestions)
The simplest thing I can think of is:
[ fib x | x <- [1..1000000] ]
Since fib n > n for all n > 3.

Haskell: What is the source of error "Ambiguous type variable ... `Integral t' ... `RealFrac t' ..." in this code?

[Disclaimer] I am very new to Haskell (and any FPL for that matter), just started learning today by reading YAHT. So my code might look "funny". Any help to improve the coding style would be appreciated as well.
I was trying to write a function in Haskell that generates a list with series 1 to n for a given value of n, starting with +1 and toggling the sign first after 1 number, then 2, then 3 and so on.
e.g. series 16 should produce [1,-2,-3,4,5,6,-7,-8,-9,-10,11,12,13,14,15,-16] (1 positive, 2 negative, 3 positive, 4 negative, ...).
I found that the sign changes after each triangular number, which equals the sum of first few natural numbers.
So I wrote this code:
module Test
where
--It accepts n and k, prints numbers 1 to n, starting with +1 and toggling their sign after each triangular number
series 0 = []
series n =
if isTriangular n
then series (getPrevTri n (n-1)) ++ getSeries (odd (n + (getPrevTri n (n-1)))) ((getPrevTri n (n-1)) + 1) (n - (getPrevTri n (n-1)))
else series (getPrevTri n (n-1)) ++ getSeries (odd ((getNextTri n (n+1)) + (getPrevTri n (n-1)))) ((getPrevTri n (n-1)) + 1) (n - (getPrevTri n (n-1)))
--The sign is negative for those numbers which follow an odd triangular number AND the triangular number previous to it is even
--OR an even number AND the triangular number previous to it is odd.
getSeries sign start 0 = []
getSeries sign start n =
if sign == True
then [start] ++ getSeries True (start+1) (n-1)
else [-start] ++ getSeries False (start+1) (n-1)
--Checks whether n is a triangular number or not
isTriangular 0 = False
isTriangular n =
checkSum n 1
--Checks whether n is equal to sum of first few natural numbers, starting from k
checkSum n 0 = False
checkSum n k =
if n == (k * k + k)/ 2
then True
else if n > (k * k + k)/ 2
then checkSum n (k+1)
else False
--Gets the triangular number just smaller than n, descending from k
getPrevTri 0 k = 0
getPrevTri n k =
if k <= n
then if isTriangular k
then truncate k
else getPrevTri n (k-1)
else 0
--Gets the triangular number just greater than n, starting from k
getNextTri 0 k = 1
getNextTri n k =
if k >= n
then if isTriangular k
then truncate k
else getNextTri n (k+1)
else 0
I had to add a call to "truncate" in "getPrevTri" and "gerNextTri" since it started producing fractional numbers. But still I'm getting this error:
*Test> :load "Test.hs"
[1 of 1] Compiling Test ( Test.hs, interpreted )
Ok, modules loaded: Test.
*Test> series 16
<interactive>:1:0:
Ambiguous type variable `t' in the constraints:
`Integral t' arising from a use of `series' at <interactive>:1:0-8
`RealFrac t' arising from a use of `series' at <interactive>:1:0-8
Probable fix: add a type signature that fixes these type variable(s)
*Test>
Could someone explain what is the source of this error?
And what does surprise me is that when I tried to debug this code, I modified it to http://pastebin.ca/1932564 which produced the similar error.
And then to http://pastebin.ca/1932556 and it surprisingly caused no error.
(Please find the output at the end of the respective posts.)
What I infer from it is that a call to
isTriangular n
causes a type error in
odd n
How is it possible when Haskell is a "pure" FPL and in which functions do not have any side effects?
I used GHCi, version 6.12.3 for these codes, on a Windows 7 x64 machine.
There is no numerical type which implements both Integral (forced by odd) and RealFrac (forced by (/)). (These are typeclasses, if you don't know what I'm talking about, just wait until your tutorial shows about this)
You may replace either / by div or do an explicit cast via fromIntegral or similar. You may also do something like x/2 == 1 instead of odd x.
Edit: In your second pastebin file, you did the conversions via truncate, which is also possible.
Haskell strength is it's strong typing system, allowing you to do less programming errors but also involves the problem of having strange problem at obvious places. I would generally suggest you to provide type-informations at least at toplevel functions. (like myFunc :: Int -> Integer). This improves both readability and safety, as the compiler prompts you suddently if something went wrong. In ghci, you can easily find out about type informations via the :t command:
ghci> :t odd
odd :: (Integral a) => a -> Bool
Please notice, that you have to wrap parantheses around infix functions when using this:
ghci> :t ($)
($) :: (a -> b) -> a -> b
Because FUZxxI already gave you an answer you were looking for I will show you how your problem can be solved easier and a lot shorter. Just for information.
How would you solve your problem in your head? First, you have to 'generate' sequence containing [1,2,2,3,3,3,4,4,4,4 ... ] just to know where to change sign. That sequence, expressed in Haskell notation, would be -
numbers = concatMap (\x -> replicate x x) [1..]
Then you have to 'combine' each number of this sequence with corresponding number from sequence from 1 to n to give it proper sign - that would be -
series n = zipWith (\a b -> a*(-1)^(b `mod` 2 + 1)) [1..n] numbers
Well, and that's it. You have the solution. You can even express it as one-liner without using numbers variable. But i consider it less readable.

Error "No instance for (Num [t])" in Collatz function

I am new to Haskell, and programming in general. I am trying to define a function which generates the sequence of Collatz numbers from n. I have:
collatz n = (collatz' n) : 1
where collatz' n = (takeWhile (>1) (collatz'' n))
where collatz'' n = n : collatz'' (collatz''' n)
where collatz''' 1 = 1
collatz''' n = if (even n) then (div n 2) else ((3*2)+1)
When I run this in GHCi, I get the error:
No instance for (Num [t])
arising from the literal `2' at <interactive>:1:7
Possible fix: add an instance declaration for (Num [t])
I don't know what this means. The problem seems to be appending "1" to the list. This problem emerges because
collatz' n = (takeWhile (>0) (collatz'' n))
generates an infinite sequence of "1"s following the correct Collatz sequence; however,
collatz' n = (takeWhile (>1) (collatz'' n))
generates all Collatz numbers from n except "1". What am I doing wrong?
(:) :: a -> [a] -> [a]
Your first line collatz n = (collatz' n) : 1 forces 1 to become [a].
I guess you wanted something like (collatz' n) ++ [1]
And you have error in if (even n) then (div n 2) else ((3*2)+1) there should be ((3*n)+1 or something like that else you have collatz''' 7 = 7
ony's answer is correct, but since you're new to Haskell, maybe this is a clearer explanation. The : operator prepends a value to a list, so doing somelist : 7 is invalid since that's trying to append a value to a list. That's why (collatz' n) : 1 doesn't compile, since the type of (collatz' n) is a list of numbers.
Try replacing the : 1 with ++ [1].
Another way to go at the problem may be for you to use a Data.Sequence structure instead of a list. Sequences allow you to "snoc" a value (put a value on the back of a sequence) as well as the more usual "cons" (put it on the front of the sequence).
Another solution for you may be to use span to make your own "takeUntil" function.
Let me explain: span p xs gives you the same answer as (takeWhile p xs, dropWhile p xs) for whichever p function and xs list you'd use, the same way that splitAt n xs is the same as (take n xs, drop n xs).
Anyway, you can use span to make your own "takeUntil" function:
takeUntil p xs = taken ++ take 1 dropped where
(taken, dropped) = span p xs
This is the form that you were looking for, when you used the collatz n = (collatz' n) : 1 form.
I hope this helps.

Resources