【问题标题】:Missing a certain Haskell type conversion缺少某个 Haskell 类型转换
【发布时间】:2015-03-03 12:16:24
【问题描述】:

在 GHCiOnline 中,let listRestDiv 4 = floor(4/(fromInteger (nextPrimeDiv 4))) 确实有效,但一般

let listRestDiv n = floor(n/(fromInteger (nextPrimeDiv n)))

不接受,其中nextPrimeDiv n

给出
let nextPrimeDiv n = head [x|x<-[1..n], n `mod` x == 0, x/=1]

只返回下一个素数。

上面写着:

无法推断 (RealFrac Integer) 由使用 `floor' 引起 由 listRestDiv 的推断类型绑定的上下文 (Integral b) :: 积分 b => 整数 -> b at

到此结束。我只是不明白这里的类型。 提前感谢您的任何提示。

【问题讨论】:

  • 添加类型是个好习惯,在这种情况下它会解决问题。
  • 正如@KarolyHorvath 所指出的,为所有顶级标识符以及一些非顶级标识符和表达式编写类型签名是一种很好的做法。这样做可以让您检查编译器,以确保你们两个在继续其他事情之前就您定义的类型达成一致。虽然这个特殊的问题是一个相当简单的问题,但总有一天,你会得到一些对你来说毫无意义的可怕的类型检查器——添加尽可能多的类型签名将帮助你准确地找出错误所在。 ScopedTypeVariables 有时会很有帮助。

标签: haskell casting


【解决方案1】:

收到的实际完整错误消息提示我们解决此问题。

Prelude> let listRestDiv n = floor(n/(fromInteger (nextPrimeDiv n)))

<interactive>:8:21:
    Could not deduce (RealFrac Integer) arising from a use of `floor'
    from the context (Integral b)
      bound by the inferred type of
               listRestDiv :: Integral b => Integer -> b
      at <interactive>:8:5-59
    Possible fix: add an instance declaration for (RealFrac Integer)
    In the expression: floor (n / (fromInteger (nextPrimeDiv n)))
    In an equation for `listRestDiv':
        listRestDiv n = floor (n / (fromInteger (nextPrimeDiv n)))

<interactive>:8:28:
    Could not deduce (Fractional Integer) arising from a use of `/'
    from the context (Integral b)
      bound by the inferred type of
               listRestDiv :: Integral b => Integer -> b
      at <interactive>:8:5-59
    Possible fix: add an instance declaration for (Fractional Integer)
    In the first argument of `floor', namely
      `(n / (fromInteger (nextPrimeDiv n)))'
    In the expression: floor (n / (fromInteger (nextPrimeDiv n)))
    In an equation for `listRestDiv':
        listRestDiv n = floor (n / (fromInteger (nextPrimeDiv n)))

这里要注意的重要一点是

    Possible fix: add an instance declaration for (Fractional Integer)
    In the first argument of `floor', namely
      `(n / (fromInteger (nextPrimeDiv n)))'

所以,你所要做的就是,使用fromInteger 也为n,像这样

Prelude> let listRestDiv n = floor(fromInteger n/(fromInteger (nextPrimeDiv n)))

【讨论】:

  • 不幸的是,它就在那里被剪掉了
  • 请注意floor(fromInteger n/fromInteger ...) = n `div` ...
  • \n -&gt; n `div` nextPrimeDiv n 效率也更高,如果你是自虐狂可以写成div &lt;$&gt; id &lt;*&gt; nextPrimeDiv
  • 我投了赞成票,我喜欢这个答案。但我认为应该对其进行编辑以删除第一行,这可以理解为居高临下。对于完全不熟悉 Haskell 的人来说,阅读错误消息并确定解决方案并不简单。您可以彻底阅读它,甚至可能多次阅读,但仍会摸不着头脑。我记得当我开始使用 Haskell 时,我很难理解“实例声明”的含义。您作为重要部分突出显示的部分似乎不是 Haskell 新手在阅读时可以理解的内容。
  • @Mr. F 我同意,我改写了那句话。请检查。
猜你喜欢
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
相关资源
最近更新 更多