将数字提高到分数(Data.Ratio)次方?
Raising a number to a fractional(Data.Ratio) power?
像 2^(2%1)
这样的表达式不会在 GHCi 中进行类型检查,并且错误消息是含糊不清的。为什么这不起作用,我需要更改什么?
我无法转换为另一种类型,我想将其用于 27^(1%3)
.
等表达式
Haskell 有 三个 幂运算符:
(^) :: (Num a, Integral b) => a -> b -> a
这会使用 正积分 指数引发 任何 类型的数字。
您在键入 2^(2%3)
时收到类似 Could not deduce (Integral (Ratio a0)) arising from a use of ‘^’
的错误,因为 Data.Ratio
是 而不是 Integral
的实例。 GHC 看到 ^
想要一个 Integral
并注意到 Data.Ratio
不能在这种情况下使用。
(^^) :: (Fractional a, Integral b) => a -> b -> a
此运算符允许 负积分 指数。请记住 x^(-n) == 1/(x^n)
。这就是为什么它需要 Fractional
.
请注意,指数必须仍然是整数。 2^^(1%2)
不是 是一个 Fractional
数字。
(**) :: Floating a => a -> a -> a
这是 "catch all" 运算符。它可以将小数提高到分数次幂。然而,这使用浮点数,而不是精确的有理数。
由于我们不能 表示所有实数,他们决定在需要不精确运算时只依赖浮点数。
因此您应该使用类型转换来执行该操作。 A 可能的实现可能是:
realToFrac $ 27**(realToFrac $ 2%3) :: Rational
或者您可以定义一个新的运算符:
(*^*) :: (RealFrac a, RealFrac b) => a -> b -> a
x *^* y = realToFrac $ realToFrac x ** realToFrac y
这将允许你写:
27 *^* (2%3)
我用了两个 *
来提醒实现中使用的 **
并且我添加了一个 ^
来引用类型前两个运算符...不确定这是否有意义,或者 ^**
或 ^^*
会更好。
然而,简单地使用 Double
s 可能会更好。这实际上取决于数字代表什么以及您用它们做什么。
解决“为什么这不起作用”——Haskell 的多重指数运算符实际上非常接近地反映了数学家定义指数的方式!
- 从头开始,您只知道(直接根据定义)对于自然 n,表达式 xn表示1·x·x·x…,n 使用 x。这正是
^
实现的,它显然适用于任何数字类型(因为乘法总是被定义)。
- 通过跨越零的“反向延续”,定义 x-n 是有意义的作为1/x·x·x…。这仅在您具有乘法逆元(即分数)时才有效。嗯,
Fractional
,你懂的!这就是 ^^
所做的。
- 要定义 分数指数,您可以从考虑根开始。这些基本上就是您要的。然而,根实际上在数学上非常复杂。它们并不是真正独一无二的。这样的根的结果类型将是代表 algebraic numbers 的东西。对于大多数用户来说,没有太多理由专门处理这些数字,因此 Haskell 跳过此部分。
现在你说,好吧,但我们当然可以为特定数字定义根。 27 的三次方恰好是一个整数,但对于大多数其他数字而言,情况并非如此。不明确或部分功能是邪恶的;因此,我们需要像 Num a => a -> Rational -> Maybe a
这样的签名。但是结果 通常 是 Nothing
,所以老实说这将是一个非常无用的函数。喜欢就自己实现吧。
- 如果你直接更进一步,它会更有用:从代数切换到微积分,数学家可以访问 exponential 和对数函数,这些为你提供了所有幂表达式的覆盖面,凭借平等
xy
= (exp(ln x))y
= exp(y · ln x)。
只要 x 为正 †,此方法就有效。对于指数的定义,在数学上你需要 limits. These exist in complete spaces,即“没有孔的空间”。根据定义,实数是完整的,但有理数不是!举个例子:Rational
是“无限准确”的,即每个值实际上都是一个精确的数字。但是,实际上您只能使用有限数量的此类有理数。
OTOH,浮点类型是设计使然不准确。 This often leads to confusion,但在数学上它实际上可以很好地解释:每个 Double
值代表一个完整的 interval 实数,如果你取所有这些的单位您得到的值不仅仅是一组离散点,而是 整条实线.
这就是 Floating
class 及其实例 Double
表示完整空格的方式,以及为什么此 class 具有方法 (**) :: Floating a => a -> a -> a
.
†在complex numbers中你甚至可以定义负数的对数,尽管它再次导致唯一性问题。
像 2^(2%1)
这样的表达式不会在 GHCi 中进行类型检查,并且错误消息是含糊不清的。为什么这不起作用,我需要更改什么?
我无法转换为另一种类型,我想将其用于 27^(1%3)
.
Haskell 有 三个 幂运算符:
(^) :: (Num a, Integral b) => a -> b -> a
这会使用 正积分 指数引发 任何 类型的数字。
您在键入
2^(2%3)
时收到类似Could not deduce (Integral (Ratio a0)) arising from a use of ‘^’
的错误,因为Data.Ratio
是 而不是Integral
的实例。 GHC 看到^
想要一个Integral
并注意到Data.Ratio
不能在这种情况下使用。(^^) :: (Fractional a, Integral b) => a -> b -> a
此运算符允许 负积分 指数。请记住
x^(-n) == 1/(x^n)
。这就是为什么它需要Fractional
.请注意,指数必须仍然是整数。
2^^(1%2)
不是 是一个Fractional
数字。(**) :: Floating a => a -> a -> a
这是 "catch all" 运算符。它可以将小数提高到分数次幂。然而,这使用浮点数,而不是精确的有理数。
由于我们不能 表示所有实数,他们决定在需要不精确运算时只依赖浮点数。
因此您应该使用类型转换来执行该操作。 A 可能的实现可能是:
realToFrac $ 27**(realToFrac $ 2%3) :: Rational
或者您可以定义一个新的运算符:
(*^*) :: (RealFrac a, RealFrac b) => a -> b -> a
x *^* y = realToFrac $ realToFrac x ** realToFrac y
这将允许你写:
27 *^* (2%3)
我用了两个 *
来提醒实现中使用的 **
并且我添加了一个 ^
来引用类型前两个运算符...不确定这是否有意义,或者 ^**
或 ^^*
会更好。
然而,简单地使用 Double
s 可能会更好。这实际上取决于数字代表什么以及您用它们做什么。
解决“为什么这不起作用”——Haskell 的多重指数运算符实际上非常接近地反映了数学家定义指数的方式!
- 从头开始,您只知道(直接根据定义)对于自然 n,表达式 xn表示1·x·x·x…,n 使用 x。这正是
^
实现的,它显然适用于任何数字类型(因为乘法总是被定义)。 - 通过跨越零的“反向延续”,定义 x-n 是有意义的作为1/x·x·x…。这仅在您具有乘法逆元(即分数)时才有效。嗯,
Fractional
,你懂的!这就是^^
所做的。 - 要定义 分数指数,您可以从考虑根开始。这些基本上就是您要的。然而,根实际上在数学上非常复杂。它们并不是真正独一无二的。这样的根的结果类型将是代表 algebraic numbers 的东西。对于大多数用户来说,没有太多理由专门处理这些数字,因此 Haskell 跳过此部分。
现在你说,好吧,但我们当然可以为特定数字定义根。 27 的三次方恰好是一个整数,但对于大多数其他数字而言,情况并非如此。不明确或部分功能是邪恶的;因此,我们需要像Num a => a -> Rational -> Maybe a
这样的签名。但是结果 通常 是Nothing
,所以老实说这将是一个非常无用的函数。喜欢就自己实现吧。 - 如果你直接更进一步,它会更有用:从代数切换到微积分,数学家可以访问 exponential 和对数函数,这些为你提供了所有幂表达式的覆盖面,凭借平等
xy = (exp(ln x))y = exp(y · ln x)。
只要 x 为正 †,此方法就有效。对于指数的定义,在数学上你需要 limits. These exist in complete spaces,即“没有孔的空间”。根据定义,实数是完整的,但有理数不是!举个例子:Rational
是“无限准确”的,即每个值实际上都是一个精确的数字。但是,实际上您只能使用有限数量的此类有理数。
OTOH,浮点类型是设计使然不准确。 This often leads to confusion,但在数学上它实际上可以很好地解释:每个Double
值代表一个完整的 interval 实数,如果你取所有这些的单位您得到的值不仅仅是一组离散点,而是 整条实线.
这就是Floating
class 及其实例Double
表示完整空格的方式,以及为什么此 class 具有方法(**) :: Floating a => a -> a -> a
.
†在complex numbers中你甚至可以定义负数的对数,尽管它再次导致唯一性问题。