我对Haskell的类型系统一个相当普遍的问题。 我试图去熟悉它,我有以下功能:
getN :: Num a => a
getN = 5.0 :: Double
当我尝试编译,我得到以下错误:
Couldn't match expected type `a' against inferred type `Double'
`a' is a rigid type variable bound by
the type signature for `getN' at Perlin.hs:15:12
In the expression: 5.0 :: Double
In the definition of `getN': getN = 5.0 :: Double
据我了解这一点,功能是建立在阶级民“回归”一类。 双是在这个类( http://www.zvon.org/other/haskell/Outputprelude/Num_c.html ),所以我本来期望它会好起来的“重返”双精度在这种情况下。
有人能解释这个吗?
与签名函数Num a => a
预期用于任何类型的在类工作Num
。 实现5.0 :: Double
只适用于一个类型,而不是对所有类型之类的,所以编译器会抱怨。
泛型函数的一个例子是:
square :: (Num a) => a -> a
square x = x * x
这适用于任何类型的是Num
。 它适用于您要使用双打,整数和任何其他数字。 正因为如此它可以有,只是需要的参数是在课堂上泛型类型签名Num
。 (Type类Num
是必要的,因为该函数使用乘法*
,其定义有)
为了增加某事的回答是:Haskell是不是面向对象的。 这是不正确的Double
是的一个子类Num
,所以你不能返回Double
如果你答应返回一个多态Num
值一样可以,比方说,Java的。
当你写getN :: Num a => a
你答应返回的值是完全内多态性Num
约束。 实际上,这意味着你只能使用从功能上Num
型类,如+
, *
, -
和fromInteger
。
检查出存在性量化类型 。
解决这个问题的一种方法是定义一个新的数据类型
data NumBox = forall n. Num n => NumBox n
你需要-XExistentialQuantification
得到这个工作。
现在,你可以写类似
getN :: NumBox
getN = NumBox (5.0 :: Double)
您还可以定义一个NumBox
-list为
let n3 = [NumBox (4.0 :: Double), NumBox (1 :: Integer), NumBox (1 :: Int) ]