[英]Haskell type signature pi
I am very new to Haskell and functional programming.我对 Haskell 和函数式编程非常陌生。
I want to approximate pi with a programm.我想用一个程序来近似 pi。 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.这不适用于签名Int -> Double
的原因是因为(*):: Num a => a -> a -> a
和sqrt:: Floating a => a -> a
等函数要求操作数(s) 和结果都具有相同的类型。
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.因此,这意味着如果n
是Int
,则x
in x <- [1..n]
也是Int
,并且由于(^)
的类型签名是(^):: (^):: (Integral b, Num a) => a -> b -> a
,这意味着x ^ 2
与x
具有相同的类型,因此这也是一个Int
。
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
.现在出现的问题是(/):: Fractional a => a -> a -> a
需要类型为Fractional
类型类的成员,而Int
is 不是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.我们可以使用fromIntegral:: (Integral a, Num b) => a -> b
将值从Integral
类型类的成员类型转换为具有Num
类型类成员类型的值。
We thus can fix this problem with:因此,我们可以通过以下方式解决此问题:
pi_approx :: Int -> Double
pi_approx n = sqrt (6 * (sum [1 / fromIntegral (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:如果x
可以很大,正如@dfeuer 所说,在计算平方之前将x
转换为 double 是有意义的:
pi_approx :: Int -> Double
pi_approx n = sqrt (6 * (sum [1 / fromIntegral 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.