我在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
?
感谢。
答案 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..]]
它可能更适合这种情况,因为你的指数将是整数,虽然它可能效率稍低,因为它使用重复乘法(指数中的对数)而不是恒定时间浮点运算。
或者(如评论中所示),要坚持使用(**)
,请使用fromIntegral
从Int
上的枚举移至您正在使用的实际类型:
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
必须是枚举类型。