2012-09-11 57 views
0

在Haskell中,我有一些定义函数的问题,因为我的参数类型与所需的类型不匹配。为什么我收到类型错误?

例如,我想写一个函数,该函数需要n :: Int并生成n的平方根的从1到floor的整数列表。因此,我将有一个功能,例如:

list :: Int -> [Int] 

本来我所定义的函数,如下所示:

list :: Int -> [Int] 

list n = [1 .. floor (sqrt n)] 

当我加载sript,存在不匹配的类型的错误消息。但是,我不确定我是否与sqrt函数或floor函数的类型不匹配。错误消息如下:

No instance for (Floating Int) 
    arising from a use of 'sqrt' at pe142.hs:6:22-27 
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 expression: [1 .. floor (sqrt n)] 
Failed, modules loaded: none. 

有人可以向我解释是什么导致错误以及如何修复?

回答

6

sqrt需要Floating类的参数,例如,一个Double。你传递给它一个Int,这不是Floating类的一个实例 - 这就是错误信息告诉你的。

因此要修复错误,请在致电sqrt之前将您的Int转换为Double。您可以使用fromIntegral函数。

4

当我试试这个:

list :: Int -> [Int] 
list n = [1 .. floor (sqrt n)] 

我得到这个错误:

../src/scratch.hs:15:16: 
    No instance for (RealFrac Int) 
     arising from a use of `floor' 
    Possible fix: add an instance declaration for (RealFrac Int) 
    In the expression: floor (sqrt n) 
    In the expression: [1 .. floor (sqrt n)] 
    In an equation for `list': list n = [1 .. floor (sqrt n)] 

../src/scratch.hs:15:23: 
    No instance for (Floating Int) 
     arising from a use of `sqrt' 
    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 expression: [1 .. floor (sqrt n)] 

什么这些错误的意思是:

  • floor功能无法接受类型为Int的论点。它的论点必须是“真实分数”类型。 (请求底层数字的类型只支持整数是没有意义的。)
  • sqrt函数也不能接受类型为Int的参数。它的参数必须是浮点类型。 (平方根通常是不合理的,所以我们需要一个浮点型。)

你会发现,Haskell是非常,有什么方法可以应用于数字功能非常挑剔的,其数值类型,什么类型非常挑剔这些函数返回,它基本上不执行隐式转换。我通常会尝试让编译器推断数字代码中的类型,因为类层次结构非常复杂。如果我们离开了你的函数的类型声明,编译器推断该类型:

list :: (Floating a, Integral t, RealFrac a) => a -> [t] 

也就是说,你list功能函数需要一个浮点“真实分数”作为其参数,并产生整数作为列表其结果。因此,例如,list可以采用类型为Double的参数并生成[Integer]

即使遗漏类型声明并不意味着你不会遇到麻烦,而且你经常不得不使用显式类型转换;最典型的是您必须使用函数fromIntegral将整数类型转换为小数类型。

1

SQRT具有以下类型签名:

Floating a => a -> a 

这意味着,SQRT采用类型A的参数,并返回类型的参数。重新定义是a必须是类型Floating的类型,通常是Single或Double。 int是不是在类型类浮动,所以你需要到n转换的东西,是在类型类浮动,您可以通过添加一个调用fromIntegral做到这一点:

list n = [1 .. floor (sqrt (fromIntegral n))] 
0

这个问题被问一次周。 (这不是对你的投诉,只是一个观察,显然这让很多人感到困惑。)

简而言之,sqrt不适用于整数,只适用于浮点数。 (例如,它不适用于Int,但它的确适用于Double。)在某些编程语言中,在这种情况下,整数总是自动“升级”为浮点数;但在Haskell中,您必须手动执行此操作。

这个解决方案,其他六个人毫无疑问已经写好了,其中的一个解决方案是将fromIntegral添加到那里,以便将整数转换为浮点数。您已经拥有floor,您可以按照预期将其转换回整数。

相关问题