Haskell基本函数定义问题

exu*_*ero 5 haskell function definition

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

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

当我尝试加载模块时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.
Run Code Online (Sandbox Code Playgroud)

有什么建议?

Chr*_*ith 10

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

所以sqrt n改为sqrt (fromIntegral n).


Ezr*_*zra 9

问题的原因

sqrt功能的类型是

sqrt :: (Floating a) => a -> a
Run Code Online (Sandbox Code Playgroud)

你可以输入:t sqrtghci 来检查这个.

Int不是一个实例Floating,这就是你看到第二个错误的原因.

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

floor :: (RealFrac a, Integral b) => a -> b
Run Code Online (Sandbox Code Playgroud)

该函数期待一个实例RealFrac,并且您正在提供Int.

键入:info RealFrac:info Floating显示两者都没有实例Int,这就是错误主体所说的原因

没有实例... Int


解决方案

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

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

fromIntegral :: (Integral a, Num b) => a -> b
Run Code Online (Sandbox Code Playgroud)

使用fromIntegral是必要的,因为进入的类型是Int,但功能floorsqrt对类型进行操作RealFrac,并Floating分别.

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

对他的程序进行更改将得到以下最终结果,该结果可以按您的要求工作:

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

进一步阅读

有两个很好的资源可以准确理解正在发生的事情是Haskell教程关于Type ClassesNumbers的部分.