回答
这样共有三种幂运算符:(^)
,(^^)
和(**)
。 ^
是非负整数幂,^^
是整数幂,和**
是浮点幂:
(^) :: (Num a, Integral b) => a -> b -> a
(^^) :: (Fractional a, Integral b) => a -> b -> a
(**) :: Floating a => a -> a -> a
原因是键入安全:数值运算的结果通常具有相同的类型作为输入参数(一个或多个) 。但是,您无法将Int
提升为浮点功率,并得到Int
类型的结果。所以类型系统会阻止你这样做:(1::Int) ** 0.5
会产生一个类型错误。 (1::Int) ^^ (-1)
也是如此。
另一种方法来把这个:Num
类型^
下关闭(他们不需要有乘法逆),Fractional
类型^^
下关闭,Floating
类型**
封闭。由于Int
没有Fractional
实例,因此无法将其提升为负值。
理想情况下,^
的第二个参数将被静态限制为非负数(目前,1^(-2)
引发运行时异常)。但Prelude
中没有自然数字的类型。
它没有定义两个运算符 - 它定义了三个!从报告:
有三两个参数幂操作:(
^
)提出任何数量的非负整数次幂,(^^
)抛出一个小数任何整数次幂,和(**
)有两个浮动点参数。对于任何x
,x^0
或x^^0
的值为1,包括零;0**y
未定义。
这意味着有三个不同的算法,其中两个得到准确的结果(^
和^^
),而**
给出近似的结果。通过选择要使用的运算符,您可以选择要调用的算法。
^
要求其第二个参数是Integral
。如果我没有弄错,如果你知道你正在使用一个整数指数,那么实现会更有效率。另外,如果你想要类似2^(1.234)
的东西,即使你的基数是一个整数,2,你的结果显然是小数。你有更多的选择,这样你可以更严格地控制哪些类型进出指数函数。
Haskell的类型系统与其他类型的系统(如C,Python或Lisp)没有相同的目标。鸭子打字(几乎)与Haskell思维模式相反。
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 **
此,如果你打开多参数类型的类扩展并未真正发挥作用,甚至,因为实例选择需要更加聪明比哈斯克尔目前允许。
关于这个不能实现的陈述仍然正确吗? IIRC,haskell可以选择多参数类型类的第二个参数,严格按照第一个参数确定。除此之外还有另外一个无法解决的问题吗? – RussellStewart
@singular这仍然是事实。例如,第一个参数不会确定第二个参数,例如,您希望指数既是“Int”又是“Integer”。为了能够拥有这三个实例声明,实例解析必须使用回溯,并且没有Haskell编译器实现这一点。 – augustss
_“类型系统不够强大”_参数仍然持有截至2015年3月? –
- 1. RSA的模数求幂的负指数
- 2. 如何在Clojure中创建一个负指数的幂函数?
- 3. Ruby 1.8.7中的求幂指数返回错误的答案
- 4. 使用MathNet在C#中给定指数的幂律分布
- 5. 在OO中指定数据类型Haskell
- 6. 如何使用Python估计指数截断幂律的参数?
- 7. Sass中的求幂
- 8. Round IO Double到指定的位数 - Haskell
- 9. Python:用指数截点绘制幂律函数
- 10. VBA - 模数求幂
- 11. Mathematica求幂并找到一个指定的系数
- 12. 如何使用Python估计幂律分布的指数?
- 13. 估计幂律分布的指数截断
- 14. 非结构化p2p网络的幂律指数是多少?
- 15. 的BigInteger幂与负数
- 16. 检查2的幂数
- 17. Python中的元素幂函数H2OFrame
- 18. 在javascript中乘以10的幂数值
- 19. Haskell有指针吗?
- 20. 模幂在Java中
- 21. C++中的模幂运算
- 22. Haskell中整数的位数
- 23. Haskell FFI - 你能从Haskell数据结构中获得一个C指针吗?
- 24. 时间幂生成函数
- 25. 幂函数Intel汇编
- 26. 除以零幂函数
- 27. 混淆F#List.Fold(幂函数)
- 28. HTTP幂等和非幂等方法?
- 29. 幂次幂贴图效率如何?
- 30. 如何在Haskell中获取指针值?
我不完全同意Haskell类型的思维方式与鸭打字相反。 Haskell类型类很像鸭子打字。 '鸭子嘎嘎嘎嘎:: a - >嘎嘎'定义了我们对鸭子的期望,然后每个实例指定了一些可以像鸭子一样行事的东西。 – augustss
@augustss我明白你来自哪里。但鸭子打字背后的非正式的座右铭是“如果它看起来像鸭子,像鸭子一样,像鸭子一样呱呱叫,那么它就是一只鸭子。”在Haskell中,除非它被声明为'Duck'的实例,否则它不是鸭子。 –
的确如此,但这正是我对Haskell的期望。你可以做任何你想吃鸭子的东西,但是你必须明确地说明它。我们不想把我们没有要求的东西误认为是鸭子。 – augustss