haskell电源功能

时间:2011-05-01 23:09:04

标签: function haskell overloading

如何编写一个利用以下事实的幂函数:将x提高到幂n(其中n是正整数),如果n是偶数,你可以通过平方半找到x的n次幂那力量。例如,x ^ 12是x ^ 6 * x ^ 6。对于奇数功率,只需从功率中减去1,然后将较小功率的结果乘以x。例如,x ^ 13是x * x ^ 12,其是x * x ^ 6 * x ^ 6。递归地,可以找到任何功率而不是将x乘以指示的次数。 我想出了这个

power x n
    | n == 0  =  1
    | x == 0  =  0
    | even n = ( power x (n / 2) ) * ( power x (n / 2) )
    | odd n = x * ( power x ((n - 1) / 2)) * ( power x ((n - 1) / 2) )

但是我收到错误说错误 - 未解决的重载 *类型:(积分a,分数a)=>整数 * 表达:力量2 2

4 个答案:

答案 0 :(得分:4)

这里发生的是一种常见的类型不匹配。首先,请查看even的类型签名:even :: (Integral a) => a -> Boolodd有类似的签名。因此,您可以看到evenodd采用任何类型的Integral类型类并对其进行评估。然后查看/(/) :: (Fractional a) => a -> a -> a的签名。 /仅采用Fractional种类型,而非Integral类型。这两种函数都不可能评估一种类型。在这种情况下,有一个简单的解决方法:使用div代替/。请注意,如果您使用div作为中缀函数(将其置于参数之间),则需要在div周围添加反引号。

答案 1 :(得分:2)

查看even的类型,并将其与/的类型进行比较。

答案 2 :(得分:1)

现在您的代码正在运行:Haskell不会自动记忆函数,因此您在最后两行计算两次递归调用power。我建议引入一个简单的函数sqr k = k * k并使用它。有几种方法:一个单独的功能;一个where条款;和let

我更希望let

power _ 0 = 1
power 0 _ = 0
power x n  = let sqr k = k * k
                 half_n = n `div` 2  
                 sqrHalfPower = sqr ( power x half_n )
             in if even n then sqrHalfPower else x * sqrHalfPower 

正如您所见,模式匹配处理前两种情况。然后let定义了一些有用的表达式,可以在in中使用。请注意,对于奇数,(n-1) `div` 2给出与n `div` 2相同的结果,因此我们可以统一这两种情况。

答案 3 :(得分:0)

我认为,计算能力的最快方法是:

     pow:: Integer->Integer->Integer
     pow x n  |(n==1) = x
              |even n = (pow x ( div n 2))*(pow x ( div n 2)) 
              |odd n  = x * (pow x (n-1))

您也可以使用“Int”代替“Integer”(在签名中替换Int上的Integer!)。