【问题标题】:Power Function in Haskell: No instance for (Floating Int) arising from a use of `**'Haskell 中的幂函数:没有因使用“**”而产生 (Floating Int) 的实例
【发布时间】:2014-04-29 12:49:23
【问题描述】:

我有以下功能:

probIndex idx xs = 
  xs!!idx+mult
  where mult = round(2**idx)

当我尝试在 ghci 中加载它时,它显示以下错误:

Prelude> :load bn.hs
[1 of 1] Compiling Main             ( bn.hs, interpreted )

bn.hs:31:16:
    No instance for (RealFrac Int)
      arising from a use of `round'
    Possible fix: add an instance declaration for (RealFrac Int)
    In the expression: round (2 ** idx)
    In an equation for `mult': mult = round (2 ** idx)
    In an equation for `probIndex':
        probIndex idx xs
          = xs !! idx + mult
          where
              mult = round (2 ** idx)

bn.hs:31:23:
    No instance for (Floating Int)
      arising from a use of `**'
    Possible fix: add an instance declaration for (Floating Int)
    In the first argument of `round', namely `(2 ** idx)'
    In the expression: round (2 ** idx)
    In an equation for `mult': mult = round (2 ** idx)
Failed, modules loaded: none.
Prelude> 

为什么会发生? 2**idx 返回浮点数,但 round 将其转换为整数,所以一切都是整数。那些“Floating”和“RealFrac”是从哪里来的?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    您的代码被解析为

    probIndex idx xs = (xs !! idx) + mult
      where mult = round (2**idx)
    

    现在,

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

    这使它成为idx :: (Floating a) => a,但是

    Prelude> :t (!!)
    (!!) :: [a] -> Int -> a
    

    这使它成为idx :: Int。因此,寻找(Floating Int) 实例的尝试失败。与来自round :: (RealFrac a, Integral b) => a -> bRealFrac 类似。

    无耻的插头:你可以看到更多关于类型推导的信息,例如in this answer :))。

    【讨论】:

      【解决方案2】:

      (**) 是浮点数的幂函数。对于整数,您应该使用整数幂 (^):

      probIndex idx xs = 
        xs!!idx + 2^idx
      

      【讨论】:

        【解决方案3】:

        表达式xs!!idx+mult被解析为

        (xs !! idx) + mult
        

        (!!) 的类型是

        >> :t (!!)
        (!!) :: [a] -> Int -> a
        

        表示idx :: Int。现在你有

        >>> mult = round (2 ** idx)
        

        (**)的类型是

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

        因为idx :: Int 你可以专攻(**) :: Floating Int => Int -> Int -> Int,这是你遇到问题的地方 - Int 不是Floating 的实例。为了解决这个问题,您可以改为编写

        >>> mult = round (2 ** fromIntegral idx)
        

        这会将idx 强制转换为小数类型,并满足类型检查器的要求。或者,如果原始表达式的解析不是您想要的,您可以简单地将其替换为

        xs !! (idx + mult) where mult = ...
        

        并且您的代码应该正确输入检查。

        【讨论】:

        • 谢谢,它有帮助。我很抱歉另一个新手问题。如何阅读 (**) :: Floating a => a -> a -> a ?我知道 a->a->a 是一个函数,它接受两个类型为 a 的参数并返回一个类型为 a 的值,但是如何解释“浮动 a =>”?
        • Floating a => 表示“此类型适用于作为 Floating 实例的任何类型 a”。所以a 可以是FloatDouble 或其他几个(列出here
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多