Reputation: 5
I am writing the haversine formula in haskell. In one version of my function, the definition and declarations are as follows:
haversine :: Double -> Double -> Double -> Double -> Double
haversine lat1 lon1 lat2 lon2 = let dlon = (toRad lon2) - (toRad lon1)
dlat = (toRad lat2) - (toRad lat1)
a = sin(dlat/2)^2 + cos(lat1)*cos(lat2)*sin(dlon/2)^2
c = 2 * asin(sqrt(a))
in c*r
This function compiles fine. When I change the declaration to:
haversine :: (Double a) => a -> a -> a -> a -> a
I get the following error:
• Expecting one fewer argument to ‘Double’
Expected kind ‘* -> *’, but ‘Double’ has kind ‘*’
• In the type signature:
haversine :: (Double a) -> a -> a -> a -> a -> a
To my knowledge, by writing (Double a), I am subjecting the rest of the parameters labeled 'a' to the Double type class constraint. Why does the latter declaration result in this error?
Upvotes: 0
Views: 102
Reputation: 89043
1) Double a
isn't a valid constraint. You're looking for Floating a
2) Constraints are given on the left hand side of a =>
, unlike function arguments which are on the left hand side of a ->
.
So to compile, your code should be
haversine :: Floating a => a -> a -> a -> a -> a
haversine lat1 lon1 lat2 lon2 = let dlon = (toRad lon2) - (toRad lon1)
dlat = (toRad lat2) - (toRad lat1)
a = sin(dlat/2)^2 + cos(lat1)*cos(lat2)*sin(dlon/2)^2
c = 2 * asin(sqrt(a))
in c*r
Assuming you have globally defined
r :: Floating a => a
toRad :: Floating a => a -> a
Upvotes: 4
Reputation: 62808
In Haskell, a type and a class are two different things.
There is a type named Double
.
There is no class named Double
.
Also, a class constraint must be followed by =>
, not ->
.
You can constrain a variable by a class such as Eq
, Show
, etc. If you want it to be a specific type... well, just write that type instead of a variable.
Upvotes: 4