我有以下Haskell代码:
two :: Integer -> Integer
two i = toInteger(2 ** i)
为什么不起作用?
答案 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
,而不是Integral
,toInteger
是错误的功能。 round
是更好的选择。
two :: Integer -> Integer
two i = round(2 ** fromIntegral(i))
这现在有效。