I am very new to Haskell and functional programming.
I want to approximate pi with a programm. My code works but only without the type-signature. Yet the task is to write a list-comprehension that fits the given type-signature so I probably have to change sth in my list-comprehension.
pi_approx :: Int -> Double
pi_approx n = sqrt (6 * (sum [1 / x^2 | x <- [1..n]]))
The reason that this does not work with the signature Int -> Double
is because functions like (*):: Num a => a -> a -> a
and sqrt:: Floating a => a -> a
require that the operand(s) and the result all have the same type.
This thus means that if n
is an Int
, then x
in x <- [1..n]
is also an Int
, and since the type signature of (^)
is (^):: (^):: (Integral b, Num a) => a -> b -> a
, it means that x ^ 2
has the same type as x
, and this is thus an Int
as well.
The problem that now arises is that (/):: Fractional a => a -> a -> a
requires the type to a member of the Fractional
typeclass, and an Int
is is not Fractional
.
We can make use of fromIntegral:: (Integral a, Num b) => a -> b
to convert a value from a type that is a member of the Integral
typeclass to value with a type that is a member of the Num
typeclass.
We thus can fix this problem with:
pi_approx :: Int -> Double
pi_approx n = sqrt (6 * (sum [1 / (x^2) | x <- [1..n]]))
if x
can be large, it makes sense, as @dfeuer says , to convert x
to a double before calculating the square:
pi_approx :: Int -> Double
pi_approx n = sqrt (6 * (sum [1 / x^2 | x <- [1..n]]))
This then produces:
Prelude> pi_approx 1
2.449489742783178
Prelude> pi_approx 2
2.7386127875258306
Prelude> pi_approx 10
3.04936163598207
Prelude> pi_approx 20
3.094669524113704
Prelude> pi_approx 100
3.1320765318091053
Prelude> pi_approx 200
3.136826306330968
Prelude> pi_approx 1000
3.1406380562059946
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.