Haskell中的exp x和类型签名

时间:2014-06-29 20:57:44

标签: haskell ghc ghci

我在GHCi中将自定义指数exp'函数定义为:

let exp' x = sum $ take 100 [(x**k) / factorial k | k <- [0..]]

产生以下类型签名:

#> :t exp'
exp' :: (Enum a, Floating a) => a -> a

但是,我希望它与exp函数匹配,即

#> :t exp
exp :: Floating a => a -> a

有人可以解释我的Enum a => a函数的exp'类型约束吗?为什么不只是Floating a => a

感谢。

2 个答案:

答案 0 :(得分:6)

它起源于k <- [0..] - 使用Enum类的人。

然后传播到最终类型签名中,因为您使用(**)进行求幂,期望它的参数类型相同:

(**) :: Floating a => a -> a -> a

一种选择是使用(^)代替取词:

(^) :: (Integral b, Num a) => a -> b -> a

您还需要将factorial k转换为正确的类型,例如fromIntegral

exp' x = sum $ take 100 [(x^k) / fromIntegral (factorial k) | k <- [0..]]

它可能更适合这种情况,因为你的指数将是整数,虽然它可能效率稍低,因为它使用重复乘法(指数中的对数)而不是恒定时间浮点运算。

或者(如评论中所示),要坚持使用(**),请使用fromIntegralInt上的枚举移至您正在使用的实际类型:

let exp' x = sum $ take 100 [(x**fromIntegral k) / fromIntegral (factorial k)
                                                        | k <- [0..]]

答案 1 :(得分:1)

[0..]转换为

enumFrom 0

enumFrom的类型为Enum a => a -> [a],因此编译器会推断k必须是枚举类型。