为什么在Haskell 0 ^ 0 == 1?

时间:2017-07-19 02:56:10

标签: haskell

为什么在Haskell 0 ^ 0 == 1?为什么不0 ^ 0 == 0?或者也许应该引起一些错误...

*Main> 0^0
1
*Main> 0**0
1.0

先谢谢

  

GHCi,版本7.10.3

4 个答案:

答案 0 :(得分:9)

当你查看签名时,这有点意义。

(^) :: (Num a, Integral b) => a -> b -> a

这个设计用于非负整数指数。它可能是递归实现的,所以它的行为就像重复乘法一样。因此,对于零功率而言,任何事物都是一个"是先例的规则,因为我们真的在谈论重复乘法。

(^^) :: (Fractional a, Integral b) => a -> b -> a

这个很像前一个,除了它也适用于负指数,因为它的基数是小数。尽管如此,它的行为类似于重复乘法或重复除法(如果指数分别为正或负),所以再次重复这些操作中的任何一个零时都应该导致乘法身份1。< / p>

(**) :: Floating a => a -> a -> a

在Haskell中,浮点类型通常符合IEEE标准,IEEE特别将pow(0.0, 0.0)定义为1.0。因此,我想,Haskell只是符合标准,因此在这种情况下它与其他语言的行为一致。

答案 1 :(得分:2)

Haskell就是这样做的,因为数学以这种方式定义它。数学就是这样做的,因为0⁰= 1·0⁰,即1乘以其他零次,即1 不乘以任何。数学家认为遵守规则是更有意义的,即第零次幂的任何东西都是1(无效产品),而不是任何幂为零的规则。

当你尝试用乘法和除法来定义指数时,这很有意义。例如,如果您尝试在Haskell中定义^,则可能会出现:

(^) a b = product $ replicate b a

这相当于:

(^) a b = foldr (*) 1 (replicate b a)

包含零数字的列表为空。空列表的乘积为1,否则很多事情都会中断,例如product (xs++[])不等于(product xs) * (product [])

或者如果您编写了最简单的递归解决方案:

(^) _ 0 = 1
(^) a b = a*(a^(b-1))

除了基本和递归情况之外,您还需要一个特殊情况,将0⁰定义为除1以外的对数。

PS

正如@leftroundabout指出的那样,我的答案假设我们正在使用离散数学。计算机科学家几乎都是,而Haskell是由学术计算机科学家设计的。

如果我们在计算机上使用连续函数,我们必须进行数值近似。在这种情况下,最有效的实现将是使用我们正在运行的机器的FPU的实现。 2017年,这将遵循IEEE标准,即标准为pow(0.0,0.0)= 1.0。

编写和证明关于符合约定的指数函数的语句只是稍微简单一些。

答案 2 :(得分:0)

这只是一个数学定律。任何提升到0幂的正数都等于1.应该没有错误

答案 3 :(得分:0)

Haskell是函数式编程语言。功能语言在其基础上使用λ-calculus 。在λ演算中使用Church编码对数字文字进行编码。因此,如果您使用Church对0^0进行编码,然后使用β减少对λ项进行标准化,则会得到1,如下所示:

0^0 = (λn.λm.λs.λz.m n s z) (λs.λz.z) (λs.λz.z) = λs.λz.s z = 1

我认为这可以解释为什么Haskell决定遵循选择的模型。