As an uni assignment, I was supposed to write a function with the type declaration:
pi_approx :: Int -> Double
and this was my first attempt:
pi_approx :: Int -> Double
pi_approx x = let total = sum [1 / (y^2) | y <- [1..x]]
in sqrt (6 * total)
which threw the below error:
pi_approx.hs:4:8: error:
* Couldn't match expected type `Double' with actual type `Int'
* In the expression: sqrt (6 * total)
In the expression:
let total = sum [1 / (y ^ 2) | y <- ...] in sqrt (6 * total)
In an equation for `pi_approx':
pi_approx x = let total = sum ... in sqrt (6 * total)
|
4 | in sqrt (6 * total)
| ^^^^^^^^^^^^^^^^
I went step by step trying to understand why the interpreter treats it as an Int:
level1 :: Fractional a => a -> a
level1 x = 1 / (x^2)
So far so good.
level2 :: (Enum a, Fractional a) => a -> [a]
level2 x = [level1 y | y <- [1..x]]
Also as expected.
level3 :: (Enum a, Fractional a) => a -> a
level3 x = sum (level2 x)
No Int to be seen...
level4 :: (Enum a, Fractional a) => a -> a
level4 x = 6 * (level3 x)
and finally
level5 :: (Floating a, Enum a) => a -> a
level5 x = sqrt (level4 x)
And having gone down this rabbit hole I'm no closer to my answer. I got it running with fromIntegral
pi_approx :: Int -> Double
pi_approx x = let total = sum [(fromIntegral 1) / ((fromIntegral y)^ (fromIntegral 2)) | y <- [1..x]]
in sqrt (6*total)
but it got me nowhere nearer to understanding what caused the error in the first version. Could someone explain what I'm missing? Why was sqrt (6*total) treated as an Int?