我exp'在GHCi中定义了自定义取幂函数:
let exp' x = sum $ take 100 [(x**k) / factorial k | k <- [0..]]
Run Code Online (Sandbox Code Playgroud)
产生以下类型签名:
#> :t exp'
exp' :: (Enum a, Floating a) => a -> a
Run Code Online (Sandbox Code Playgroud)
但是,我原以为它与exp函数的匹配,即
#> :t exp
exp :: Floating a => a -> a
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释Enum a => a我的exp'函数的类型约束吗?为什么不呢Floating a => a?
谢谢.
它起源于k <- [0..]- 使用Enum该类的desugars .
然后它传播到最终类型签名,因为你正在使用(**)指数,它希望它的参数是相同的类型:
(**) :: Floating a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
一种选择是使用(^)取幂来代替:
(^) :: (Integral b, Num a) => a -> b -> a
Run Code Online (Sandbox Code Playgroud)
您还需要转换factorial k为正确的类型,例如fromIntegral:
exp' x = sum $ take 100 [(x^k) / fromIntegral (factorial k) | k <- [0..]]
Run Code Online (Sandbox Code Playgroud)
它可能更适合这种情况,因为你的指数将是整数,虽然它可能效率稍低,因为它使用重复乘法(指数中的对数)而不是恒定时间浮点运算.
或者(如评论中所示),坚持使用(**),用于fromIntegral从枚举移动Int到您正在使用的实际类型:
let exp' x = sum $ take 100 [(x**fromIntegral k) / fromIntegral (factorial k)
| k <- [0..]]
Run Code Online (Sandbox Code Playgroud)