Haskell:功能声明不同

时间:2017-07-13 15:11:29

标签: haskell

我正在编写haskell中的hasrsine公式。 在我的函数的一个版本中,定义和声明如下:

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

这个功能很好。当我将声明更改为:

haversine :: (Double a) => a -> a -> a -> a -> a

我收到以下错误:

• Expecting one fewer argument to ‘Double’
  Expected kind ‘* -> *’, but ‘Double’ has kind ‘*’
• In the type signature:
    haversine :: (Double a) -> a -> a -> a -> a -> a

据我所知,通过编写(Double a),我将标记为'a'的其余参数置于Double类约束中。为什么后一个声明会导致此错误?

2 个答案:

答案 0 :(得分:4)

在Haskell中,类型是两回事。

有一个名为Double类型

没有名为Double

此外,类约束必须后跟=>,而不是->

您可以通过约束变量,例如EqShow等。如果您希望它是特定的类型 ......好吧,只需写出那种类型而不是变量。

答案 1 :(得分:4)

1)Double a不是有效约束。您正在寻找Floating a

2)约束在=>的左侧给出,与->左侧的函数参数不同。

所以要编译,你的代码应该是

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

假设您已全局定义

r :: Floating a => a
toRad :: Floating a => a -> a