sky*_*ird 84 haskell exponent exponentiation
有人能告诉我为什么Haskell Prelude为取幂定义了两个独立的函数(即^和**)吗?我认为类型系统应该消除这种重复.
Prelude> 2^2
4
Prelude> 4**0.5
2.0
Run Code Online (Sandbox Code Playgroud)
Mik*_*kov 124
这样共有三种幂运营商:(^),(^^)和(**).^是非负积分求幂,^^是整数求幂,**是浮点求幂:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
原因是类型安全:数值运算的结果通常与输入参数具有相同的类型.但是你不能提高Int到浮点功率并获得类型的结果Int.因此类型系统阻止您这样做:(1::Int) ** 0.5产生类型错误.同样的道理(1::Int) ^^ (-1).
另一种方法是:Num关闭类型^(它们不需要有乘法逆),Fractional类型关闭^^,Floating类型关闭**.由于没有Fractional实例Int,你无法将其提升为负功率.
理想情况下,第二个参数^将被静态约束为非负(当前,1 ^ (-2)抛出运行时异常).但是,自然数字中没有类型Prelude.
aug*_*tss 29
Haskell的类型系统不足以将三个求幂运算符表示为一个.你真正想要的是这样的:
class Exp a b where (^) :: a -> b -> a
instance (Num a, Integral b) => Exp a b where ... -- current ^
instance (Fractional a, Integral b) => Exp a b where ... -- current ^^
instance (Floating a, Floating b) => Exp a b where ... -- current **
Run Code Online (Sandbox Code Playgroud)
即使您打开多参数类型类扩展,这也不会真正起作用,因为实例选择需要比Haskell当前允许的更聪明.
Gab*_*abe 10
它没有定义两个运算符 - 它定义了三个!来自报告:
有三个双参数取幂运算:(
^)将任意数字提升为非负整数幂,(^^)将小数提升为任何整数幂,(**)取两个浮点参数.的值x^0或x^^0为1对任何x,包括零;0**y未定义.
这意味着有三种不同的算法,其中两种给出精确的结果(^和^^),同时**给出近似的结果.通过选择要使用的运算符,您可以选择要调用的算法.