使用'**'时没有(浮动整数)的实例?

时间:2016-07-12 07:03:40

标签: haskell

我有以下Haskell代码:

two :: Integer -> Integer
two i = toInteger(2 ** i)

为什么不起作用?

3 个答案:

答案 0 :(得分:6)

(**)需要基于函数签名的浮点输入:

(**) :: Floating a => a -> a -> a
另一方面,

toInteger需要输入本质上是不可或缺的:

toInteger :: Integral a => a -> Integer

因此,您无法以两种方式使用它。也就是说,既然您似乎期待整数输入,您可以考虑使用(^),如下所示:

two :: Integer -> Integer
two i = 2 ^ i

正如@leftaroundabout在评论中正确指出的那样,(^)会因{1}}的负值而失败。这可以通过以替代方式检查值和处理来解决,如下所示:

i

答案 1 :(得分:2)

改为使用^

two i = 2 ^ i

然后没有必要将结果转换回Integral类型。

答案 2 :(得分:0)

这个原因......

two :: Integer -> Integer
two i = toInteger(2 ** i)

...无效是因为您已将i声明为整数,如果我们查看(**)的类型...

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

...它的所有参数都是相同的类型,并且该类型必须是Floating类型类的实例。 Integer不是Floating的实例。这就是“没有(浮动整数)的实例”的意思。

最简单的解决方案是使用^作为ErikR建议。它提升了一个整体力量。

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

如果您希望使用**进一步学习,请继续阅读。

因此我们需要将您的整数转换为Floating的实例类型。您可以使用fromIntegral执行此操作。如果我们这样做:

two :: Integer -> Integer
two i = toInteger(2 ** fromIntegral(i))

...我们仍然收到大量错误消息抱怨各种类型都不明确。这些并不像第一条消息那样清晰,但问题是使用toInteger,如果我们查看它的类型就会变得明显。

Prelude> :t toInteger
toInteger :: Integral a => a -> Integer

当我们将**的结果传递给toInteger时,这是Floating,而不是IntegraltoInteger是错误的功能。 round是更好的选择。

two :: Integer -> Integer
two i = round(2 ** fromIntegral(i))

这现在有效。