How would the Fibonacci's closed form code look like in haskell?
Here's a straightforward translation of the formula to Haskell:
fib n = round $ (phi^n - (1 - phi)^n) / sqrt 5
where phi = (1 + sqrt 5) / 2
This gives correct values only up to n = 75, because it uses Double precision floating-point arithmetic.
However, we can avoid floating-point arithmetic by working with numbers of the form a + b * sqrt 5! Let's make a data type for them:
data Ext = Ext !Integer !Integer
deriving (Eq, Show)
instance Num Ext where
fromInteger a = Ext a 0
negate (Ext a b) = Ext (-a) (-b)
(Ext a b) + (Ext c d) = Ext (a+c) (b+d)
(Ext a b) * (Ext c d) = Ext (a*c + 5*b*d) (a*d + b*c) -- easy to work out on paper
-- remaining instance methods are not needed
We get exponentiation for free since it is implemented in terms of the Num methods. Now, we have to rearrange the formula slightly to use this.
fib n = divide $ twoPhi^n - (2-twoPhi)^n
where twoPhi = Ext 1 1
divide (Ext 0 b) = b `div` 2^n -- effectively divides by 2^n * sqrt 5
This gives an exact answer.
Daniel Fischer points out that we can use the formula phi^n = fib(n-1) + fib(n)*phi and work with numbers of the form a + b * phi (i.e. ℤ[φ]). This avoids the clumsy division step, and uses only one exponentiation. This gives a much nicer implementation:
data ZPhi = ZPhi !Integer !Integer
deriving (Eq, Show)
instance Num ZPhi where
fromInteger n = ZPhi n 0
negate (ZPhi a b) = ZPhi (-a) (-b)
(ZPhi a b) + (ZPhi c d) = ZPhi (a+c) (b+d)
(ZPhi a b) * (ZPhi c d) = ZPhi (a*c+b*d) (a*d+b*c+b*d)
fib n = let ZPhi _ x = phi^n in x
where phi = ZPhi 0 1
Trivially, Binet's formula, from the Haskell wiki page is given in Haskell as:
fib n = round $ phi ^ n / sq5
where
sq5 = sqrt 5
phi = (1 + sq5) / 2
Which includes sharing of the result of the square root. For example:
*Main> fib 1000
4346655768693891486263750038675
5014010958388901725051132915256
4761122929200525397202952340604
5745805780073202508613097599871
6977051839168242483814062805283
3118210513272735180508820756626
59534523370463746326528
For arbitrary integers, you'll need to be a bit more careful about the conversion to floating point values.
Note that Binet's value differs from the recursive formula by quite a bit at this point:
*Main> let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
*Main> fibs !! 1000
4346655768693745643568852767504
0625802564660517371780402481729
0895365554179490518904038798400
7925516929592259308032263477520
9689623239873322471161642996440
9065331879382989696499285160037
04476137795166849228875
You may need more precision :-)
Related
The number π can be calculated with the following infinite series sum:
I want to define a Haskell function roughlyPI that, given a natural number k, calculates the series sum from 0 to the k value.
Example: roughlyPi 1000 (or whatever) => 3.1415926535897922
What I did was this (in VS Code):
roughlyPI :: Double -> Double
roughlyPI 0 = 2
roughlyPI n = e1/e2 + (roughlyPI (n-1))
where
e1 = 2**(n+1)*(factorial n)**2
e2 = factorial (2*n +1)
factorial 0 = 1
factorial n = n * factorial (n-1)
but it doesn't really work....
*Main> roughlyPI 100
NaN
I don't know what's wrong. I'm new to Haskell, by the way.
All I really want is to be able to type in a number that will give me PI at the end. It can't be that hard...
As mentioned in the comments, we need to avoid large divisions and instead intersperse smaller divisions within the factorials. We use Double for representing PI but even Double has its limits. For instance 1 / 0 == Infinity and (1 / 0) / (1 / 0) == Infinity / Infinity == NaN.
Luckily, we can use algebra to simplify the formula and hopefully delay the blowup of our Doubles. By dividing within our factorial the numbers don't grow too unwieldy too quickly.
This solution will calculate roughlyPI 1000, but it fails on 1023 with NaN because 2 ^ 1024 :: Double == Infinity. Note how each iteration of fac has a division as well as a multiplication to help keep the numbers from blowing up. If you are trying to approximate PI with a computer, I believe there are better algorithms, but I tried to keep it as conceptually close to your attempt as possible.
roughlyPI :: Integer -> Double
roughlyPI 0 = 2
roughlyPI k = e + roughlyPI (k - 1)
where
k' = fromIntegral k
e = 2 ** (k' + 1) * fac k / (2 * k' + 1)
where
fac 1 = 1 / (k' + 1)
fac p = (fromIntegral p / (k' + fromIntegral p)) * fac (p - 1)
We can do better than having a blowup of Double after 1000 by doing computations with Rationals then converting to Double with realToFrac (credit to #leftaroundabout):
roughlyPI' :: Integer -> Double
roughlyPI' = realToFrac . go
where
go 0 = 2
go k = e + go (k - 1)
where
e = 2 ^ (k + 1) * fac k / (2 * fromIntegral k + 1)
where
fac 1 = 1 % (k + 1)
fac p = (p % (k + p)) * fac (p - 1)
For further reference see Wikipedia page on approximations of PI
P.S. Sorry for the bulky equations, stackoverflow does not support LaTex
First note that your code actually works:
*Main> roughlyPI 91
3.1415926535897922
The problem, as was already said, is that when you try to make the approximation better, the factorial terms become too big to be representable in double-precision floats. The simplest – albeit somewhat brute-force – way to fix that is to do all the computation in rational arithmetic instead. Because numerical operations in Haskell are polymorphic, this works with almost the same code as you have, only the ** operator can't be used since that allows fractional exponents (which are in general irrational). Instead, you should use integer exponents, which is anyway the conceptually right thing. That requires a few fromIntegral:
roughlyPI :: Integer -> Rational
roughlyPI 0 = 2
roughlyPI n = e1/e2 + (roughlyPI (n-1))
where
e1 = 2^(n+1)*fromIntegral (factorial n^2)
e2 = fromIntegral . factorial $ 2*n + 1
factorial 0 = 1
factorial n = n * factorial (n-1)
This now works also for much higher degrees of approximation, although it takes a long time to carry around the giant fractions involved:
*Main> realToFrac $ roughlyPI 1000
3.141592653589793
The way to go in such cases is to calculate the ratio of consecutive terms and calculate the terms by rolling multiplications of the ratios:
-- 1. -------------
pi1 n = Sum { k = 0 .. n } T(k)
where
T(k) = 2^(k+1)(k!)^2 / (2k+1)!
-- 2. -------------
ts2 = [ 2^(k+1)*(k!)^2 / (2k+1)! | k <- [0..] ]
pis2 = scanl1 (+) ts2
pi2 n = pis2 !! n
-- 3. -------------
T(k) = 2^(k+1)(k!)^2 / (2k+1)!
T(k+1) = 2^(k+2)((k+1)!)^2 / (2(k+1)+1)!
= T(k) 2 (k+1)^2 / (2k+2) (2k+3)
= T(k) (k+1)^2 / ( k+1) (2k+3)
= T(k) (k+1) / (k+1 + k+2)
= T(k) / (1 + (k+2)/(k+1))
= T(k) / (2 + 1 /(k+1))
-- 4. -------------
ts4 = scanl (/) 2 [ 2 + 1/(k+1) | k <- [0..]] :: [Double]
pis4 = scanl1 (+) ts4
pi4 n = pis4 !! n
This way we share and reuse the calculations as much as possible. This leads to the most efficient code, hopefully leading to the smallest cumulative numerical error. The formula also turned out to be exceptionally simple, and could even be simplified further as ts5 = scanl (/) 2 [ 2 + recip k | k <- [1..]].
Trying it out:
> pis2 = scanl1 (+) $ [ fromIntegral (2^(k+1))*fromIntegral (product[1..k])^2 /
fromIntegral (product[1..(2*k+1)]) | k <- [0..] ] :: [Double]
> take 8 $ drop 30 pis2
[3.1415926533011587,3.141592653447635,3.141592653519746,3.1415926535552634,
3.141592653572765,3.1415926535813923,3.141592653585647,3.141592653587746]
> take 8 $ drop 90 pis2
[3.1415926535897922,3.1415926535897922,NaN,NaN,NaN,NaN,NaN,NaN]
> take 8 $ drop 30 pis4
[3.1415926533011587,3.141592653447635,3.141592653519746,3.1415926535552634,
3.141592653572765,3.1415926535813923,3.141592653585647,3.141592653587746]
> take 8 $ drop 90 pis4
[3.1415926535897922,3.1415926535897922,3.1415926535897922,3.1415926535897922,
3.1415926535897922,3.1415926535897922,3.1415926535897922,3.1415926535897922]
> pis4 !! 1000
3.1415926535897922
I made this tail-recursive function for computing square roots:
sqrt x n a = if n == 0 then a else sqrt x (n - 1) (a + x/a)/2
For some reason, it gives the wrong result when n is greater than 1, meaning when it's asked to improve the approximation, a, more than once. It returns a number that's closer and closer to 0 as n grows. I tried implementing the same recursive formula in different ways like this:
sqrt x n = if n == 0 then 1 else (a + x/a)/2 where a = sqrt x (n - 1)
sqrt x = 1:map (\a -> (a + x/a)/2) (sqrt x)
And that all works fine. It's only the first example that doesn't work and I can't figure out why, as much as I try.
The expression:
sqrt x n a = if n == 0 then a else sqrt x (n - 1) (a + x/a) / 2
is parsed as:
sqrt x n a = if n == 0 then a else (sqrt x (n - 1) (a + x/a)) / 2
So the sqrt x (n-1) (a+x/a) is seen as the numerator of a division by two. You should add brackets here:
sqrt x n a = if n == 0 then a else sqrt x (n - 1) ((a + x/a) / 2)
With the given, fix, we can for example calculate the square root of five as:
Prelude> sqrt 5 10 1
2.23606797749979
According to Wikipedia, it is:
2.23606797749978969640917366873127623544061835961152572427089…
so this is already quite close.
I am doing some arbitrary operations in Haskell as I learn, and have been playing with a list of animals with certain properties, including age.
This is my script:
module Animals where
data Animal = CatThing String Int
| DogThing String Int
deriving Show
animalList :: [Animal]
animalList = [CatThing "Spot" 2, DogThing "Rex" 5]
-- write a function that returns the string component given an animal
getName :: Animal -> String
getName (CatThing name _) = name
getName (DogThing name _) = name
-- get the age of an animal (uses "map")
getAge :: Animal -> Int
getAge (CatThing _ age) = age
getAge (DogThing _ age) = age
-- sum age
sumAge :: Int -> [Int] -> Int
sumAge _ [b, c] = foldl (+) 0 [b, c]
-- average age
???
I am stuck on how to sum using foldl'. I know there is a sum function built in, but I am really trying to practice folds, so am trying to do it that way.
Does anyone have suggestions on how to proceed?
The code for your sum looks fine, I'd use foldl' instead of foldl so you don't risk a stack overflow, and also change that [b,c] pattern to a generic variable or even better point free so it looks better and it's also more general:
sumAge :: [Double] -> [Double]
sumAge = foldl' (+) 0
As for the average, you just sum and divide by the length:
averageAge :: [Double] -> Double
averageAge ls = sumAge ls / length ls
PS. In case your ages are integer, then the first function still works, but the average need to change:
averageInt :: [Int] -> Double
averageInt ls = (fromInteger . sum) ls / (fromInteger . length) ls
TL;DR version
Sum: sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
Average:
import Data.Sequence(foldlWithIndex, fromList)
average numbers = foldlWithIndex (\a i x -> let k = fromIntegral i in (k*a + x) / (k + 1)) 0 . fromList $ numbers
Long version
If you have an interest in math, it may help to understand the design of fold functions as equivalent to discovering sequence formulas by induction.
Sum
For sum, since you have s[i+1] = s[i] + x[i+1], you can simply use addition like you did, although you may have to convert before you add:
sumAges :: [Animal] -> Int
sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
sumAgesPointFree :: [Animal] -> Int
sumAgesPointFree = foldl (flip $ (+) . getAge) 0
Average
For example, one way to calculate the average of a list using a single fold function is to use a recursive mathematical version of calculating the rolling average of a sequence: m[i+1] = (i * m[i] + x[i+1]) / (i + 1). You can see this in how you calculate the average of lists of varying sizes:
{-
Not Haskell, just attempting mathematical notation without knowing MathML in Markdown.
m: mean or average
x: an element of a list or sequence
[]: subscript
-}
m[1] = x[1]
m[2] = (x[1] + x[2]) / 2 = (m[1] + x[2]) / 2 -- m[1] = x[1], so substitute
m[3] = (x[1] + x[2] + x[3]) / 3 -- (a+b)/n = a/n + b/n, so distribute
= (x[1] + x[2]) / 3 + x[3] / 3 -- a = n/n * a, n not in {0, Infinity}
= 2/2 * (x[1] + x[2]) / 3 + x[3] / 3 -- n/n * 1/a = n/a * 1/n
= 2/3 * (x[1] + x[2]) / 2 + x[3] / 3 -- m[2] = (x[1] + x[2])/2, so substitute
= 2/3 * m[2] + x[3] / 3
= 2*m[2] / 3 + x[3] / 3
= (2*m[2] + x[3]) / 3
...
m[i+1] = (i * m[i] + x[i+1]) / (i+1)
However, since this function would require the element index as a parameter, due to the List structure's lack of (convenient) indexing, the Sequence type from the Data.Sequence module may work out better than a List, especially considering the Data.Sequence module has this really nice foldlWithIndex function:
module Average(average) where
import Data.Sequence(foldlWithIndex, fromList)
average :: Fractional a => [a] -> a
average = foldlWithIndex averageByPrevious 0 . fromList
where averageByPrevious previous index current = (coefficient*previous + current) / (coefficient + 1)
where coefficient = fromIntegral index
Then you can simply run average list where list is some list you want to find the rolling average of. This is one way to calculate the average of a list using a single fold without adding a large performance overhead as you would by running multiple O(n) functions over the same list, even considering laziness as a benefit to the performance of multiple calls.
NOTE: I will admit, this is not easy to read, so average xs = (sum xs) / (length xs) as #Lorenzo said will work much better if legibility is more important than performance here.
I want to use rational number type instead of factional type in Haskell (or float/double type in C)
I get below result:
8/(3-8/3)=23.999...
8/(3-8/3)/=24
I know Data.Ratio. However, it support (+) (-) (*) (/) operation on Data.Ratio:
1%3+3%3 == 4 % 3
8/(3-8%3) == 24 % 1
I had checked in Racket:
(= (/ 8 (- 3 (/ 8 3))) 24)
#t
What's correct way to ensure 8/(3-8/3) == 24 in Haskell?
Use an explicit type somewhere in the chain. It will force the entire calculation to be performed with the corrrect type.
import Data.Ratio
main = do
print $ 8/(3-8/3) == 24
print $ 8/(3-8/3) == (24 :: Rational)
Prints
False
True
Data.Ratio.numerator and Data.Ratio.denominator return numerator an denominator of the ratio in reduced form so it is safe to compare denominator to 1 to check if ratio is an integer.
import Data.Ratio
eq :: (Num a, Eq a) => Ratio a -> a -> Bool
eq r i = d == 1 && n == i
where
n = numerator r
d = denominator r
main = print $ (8/(3-8%3)) `eq` 24
I'm trying to make function primes which is a list of prime numbers, but somehow I have failed. The compiler throws an error I don't know how to resolve:
Error:
Ambiguous type variable 'a0'
Code:
candidates :: [Integer]
candidates = [2]++[3,5..]
primes :: [Integer]
primes = filter is_prime candidates
is_prime :: Integer -> Bool
is_prime candidate
| candidate == 1 = False
| candidate == 2 = True
| candidate == 3 = True
| otherwise = r_is_prime candidate 0
-- r as recursive
r_is_prime :: Integer -> Integer -> Bool
r_is_prime candidate order
| n_th_prime >= max_compared_prime = True
| candidate `mod` n_th_prime == 0 = False
| otherwise = if (r_is_prime candidate (order+1) ) then True else False
where
n_th_prime = candidates !! fromIntegral(order)
-- this is the line that throws an error...
max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))
In
max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))
you have a fromIntegral too much. sqrt has type
sqrt :: Floating a => a -> a
so the result of sqrt is not a member of an Integral type. And the result of ceiling is an Integral type, so the last fromIntegral is superfluous (but does not harm).
max_compared_prime = ceiling ( sqrt ( fromIntegral candidate))
is all you need in that line.
Note, however, that
n_th_prime = candidates !! fromIntegral(order)
means that to test against the n-th candidate prime, the list of candidates has to be traversed until the n-th prime has been reached. Thus testing against the n-th candidate is O(n) here instead of O(1) [Well, assuming that numbers are bounded] which a single division is.
A more efficient trial division only tries primes for the division and remembers where in the list of primes it was when it goes on to the next prime. For example
is_prime :: Integer -> Bool
is_prime n
| n < 2 = False
| n < 4 = True
| otherwise = trialDivision primes
where
r = floor (sqrt $ fromIntegral n)
trialDivision (p:ps)
| r < p = True
| otherwise = n `rem` p /= 0 && trialDivision ps
Just traverses the list of primes in order to do the trial division, hence going from one prime to the next is a simple step in the list.
You have too many fromIntegrals in
max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))
The fromIntegral applied to the result of sqrt is causing the error. If we look at the type signatures, we have:
fromIntegral :: (Num b, Integral a) => a -> b
sqrt :: Floating a => a -> a
So to properly infer the type of fromIntegral (sqrt x) Haskell needs to find a type with both Floating and Integral instances (so that the result of sqrt matches the parameter of fromIntegral). Haskell can't find such a type and so (basically) is asking you to specify one (but there isn't one). The solution is to just elide this fromIntegral:
max_compared_prime = fromIntegral ( ceiling ( sqrt ( fromIntegral candidate)))
other notes
Brackets aren't particularly idiomatic Haskell, so that line can/should be written as:
max_compared_prime = fromIntegral . ceiling . sqrt . fromIntegral $ candidate
Furthermore, the result of ceiling doesn't need to be converted, so it can even be:
max_compared_prime = ceiling . sqrt . fromIntegral $ candidate
Remove 'fromIntegral' from before 'sqrt', as:
max_compared_prime = fromIntegral ( ceiling ( sqrt ( fromIntegral candidate)))
The types are:
sqrt :: Floating a => a -> a
fromIntegral :: (Integral a, Num b) => a -> b
the output of sqrt is 'Floating', not Integral.