【问题标题】:Haskell basic function definition problemHaskell基本函数定义问题
【发布时间】:2011-03-06 04:39:02
【问题描述】:

我正在学习 Haskell,我正在尝试编写一个函数来返回一个数字的因子列表。这是我所拥有的:

factors :: Int -> [Int]
factors n = [x | x <- [2..s], n `mod` x == 0]
    where s = floor (sqrt n)

当我尝试在ghci 中加载模块时,出现两个错误,

p003.hs:3:14:
    No instance for (RealFrac Int)
      arising from a use of `floor' at p003.hs:3:14-27
    Possible fix: add an instance declaration for (RealFrac Int)
    In the expression: floor (sqrt n)
    In the definition of `s': s = floor (sqrt n)
    In the definition of `factors':
        factors n = [x | x <- [2 .. s], n `mod` x == 0]
                  where
                      s = floor (sqrt n)

p003.hs:3:21:
    No instance for (Floating Int)
      arising from a use of `sqrt' at p003.hs:3:21-26
    Possible fix: add an instance declaration for (Floating Int)
    In the first argument of `floor', namely `(sqrt n)'
    In the expression: floor (sqrt n)
    In the definition of `s': s = floor (sqrt n)
Failed, modules loaded: none.

有什么建议吗?

【问题讨论】:

    标签: function haskell definition


    【解决方案1】:

    参数的类型为Int,因此您无法为其计算平方根。您需要先将其转换为浮点类型,您可以使用 fromIntegral 来完成。与其他一些语言不同,Haskell 不会自动将整数提升为浮点数(也不会进行任何其他自动类型转换)。

    所以将sqrt n 更改为sqrt (fromIntegral n)

    【讨论】:

      【解决方案2】:

      问题的原因

      sqrt函数的类型是

      sqrt :: (Floating a) => a -> a
      

      您可以通过在 ghci 中输入 :t sqrt 来检查。

      Int 不是Floating 的实例,这就是您看到第二个错误的原因。

      第一个错误的原因是一样的;检查:t floor 显示类型是:

      floor :: (RealFrac a, Integral b) => a -> b
      

      函数需要RealFrac 的实例,而您提供的是Int

      输入 :info RealFrac:info Floating 表明两者都没有 Int 的实例,这就是错误正文显示的原因

      没有 ... Int 的实例


      解决办法

      解决这个问题的方法,是确保类型正确;它们必须是正确类型类的成员。

      一个简单的方法是使用fromIntegral 函数,:t 揭示的类型是:

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

      使用fromIntegral 是必要的,因为传入的类型是Int,但函数floorsqrt 分别对RealFracFloating 类型进行操作。

      这是允许的,因为从类型签名中可以看出,fromIntegral 返回一个Num 的实例,其中包括RealFracFloating 类型。您可以通过在 ghci 中输入 :info Num:info Float 并查看输出来说服自己。

      对您的程序进行更改将产生以下最终结果,这应该可以按您的意愿工作:

      factors :: Int -> [Int]
      factors n = [x | x <- [2..s], n `mod` x == 0] 
          where s = floor (sqrt $ fromIntegral n) 
      

      进一步阅读

      Haskell 教程的 Type ClassesNumbers 部分是两个很好的资源,可以帮助您准确了解正在发生的事情。

      【讨论】:

      • 我想你可能想要 (div 2) 而不是 sqrt。
      猜你喜欢
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-02
      • 1970-01-01
      相关资源
      最近更新 更多