在Haskell中,我在定义函数时遇到一些问题,因为我的参数类型与所需的类型不匹配。
例如,我想编写一个带n :: Int
的函数,并生成从1到floor
的平方根n
的整数列表。因此,我希望有一个功能,如:
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.
有人可以向我解释导致错误的原因以及如何修复错误吗?
答案 0 :(得分:6)
sqrt
需要Floating
类的参数,例如一个Double
。您传递的是Int
,它不是Floating
类的实例 - 这就是错误消息告诉您的内容。
因此,要修正错误,请在致电Int
之前将Double
转换为sqrt
。您可以使用fromIntegral
功能。
答案 1 :(得分: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
将整数类型转换为小数类型。
答案 2 :(得分:1)
sqrt具有以下类型签名:
Floating a => a -> a
这意味着sqrt接受类型为a的参数并返回类型为a的参数。 restiction是a必须是float类型中的一个类型,通常是Single或Double。 Int不在类型Floating中,因此您需要将n转换为类型为Floating的类型,您可以通过添加对fromIntegral
的调用来执行此操作:
list n = [1 .. floor (sqrt (fromIntegral n))]
答案 3 :(得分:0)
每周一次询问这个问题。 (这不是对你的抱怨,只是一个观察。显然这让很多人感到困惑。)
简而言之,sqrt
不适用于整数,仅适用于浮点数。 (例如,它不适用于Int
,但它适用于Double
。)在某些编程语言中,在这种情况下,整数总是自动“提升”为浮点数;但是在Haskell中你必须手动完成。
解决方案,正如其他六个人毫无疑问已经写过的那样,是在那里坚持使用fromIntegral
来从整数转换为浮点数。你已经拥有floor
,这可以让你在之后转换回整数,正如你所期望的那样。