Haskell 什么';这两种函数类型定义之间的区别是什么?

Haskell 什么';这两种函数类型定义之间的区别是什么?,haskell,Haskell,对于以下普通函数定义: printLength1::(Num a)=>String->a printLength1 s = length s printLength2::String->Int printLength2 s = length s 为什么它们不一样?在什么情况下,我应该选择一种而不是另一种 对于printLength1,我得到了这个错误: Couldn't match type `a' with `Int' `a' is a rigid type

对于以下普通函数定义:

printLength1::(Num a)=>String->a
printLength1 s = length s


printLength2::String->Int
printLength2 s = length s
为什么它们不一样?在什么情况下,我应该选择一种而不是另一种

对于printLength1,我得到了这个错误:

Couldn't match type `a' with `Int'
      `a' is a rigid type variable bound by
          the type signature for rpnc :: String -> a at test.hs:20:1
    In the return type of a call of `length'
    In the expression: length s
    In an equation for `rpnc': rpnc s = length s
我理解这个错误。但是我怎么才能解决这个问题呢? 我已经读过一些关于刚性类型变量的帖子,但仍然不明白如何修复它。

引用:

注意:此函数的类型为numLongChains::Int,因为出于历史原因,length返回的是Int而不是Num a。如果我们想返回一个更一般的Num a,我们可以在得到的长度上使用fromIntegral


第一种类型的签名更一般。这意味着结果可以是任意
Num
——它的返回类型是多态的。因此,第一个函数的结果可以用作
Int
Integer
或任何其他
Num
实例

问题是
length
返回的是
Int
而不是任何
Num
实例。您可以使用积分中的
来解决此问题:

printLength1 :: Num a => String -> a
printLength1 s = fromIntegral $ length s

请注意,
fromIntegral的签名。长度
(这是上面代码的无点版本)是
numc=>[a]->c
。这与您为
printLength1
函数指定的签名匹配。

谢谢。我希望语言中不再隐藏这样的怪癖。@osager这不是怪癖,这是类型系统中非常重要的一部分。多态类型(至少排名1的多态类型)通过使用方式转变为具体类型。如果您编写的类型签名声称类型是多态的,那么它实际上需要是多态的。
Num
类不是一个怪癖,但是您可以合理地认为
length
是一个
Int
而不是
Num a
是一个怪癖。
Data.List.genericLength
具有类型
Num a=>b]->a
@Grazer:很高兴知道。必须有一个特殊的
length
通用版本这一事实正好说明这有点奇怪。