Haskell基本函数定义问题

时间:2011-03-06 04:39:03

标签: function haskell definition

我正在学习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.

有什么建议吗?

2 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分:9)

问题的原因

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,但函数floorsqrtRealFracFloating类型进行操作, 分别。

这是允许的,因为正如您从类型签名中看到的那样,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) 

进一步阅读

有关正确了解正在发生的事情的两个很好的资源是关于Type ClassesNumbers的Haskell教程部分。