2009-10-07 81 views
14

我對Haskell的類型系統有一個相當普遍的問題。我試圖去熟悉它,我有以下功能:在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 

據我瞭解這一點,函數設置爲「返回」類Num中的類型。雙是在這個類(http://www.zvon.org/other/haskell/Outputprelude/Num_c.html),所以我本以爲在這種情況下可以「返回」一個雙。

有人可以解釋這個嗎?

回答

15

具有簽名Num a => a的函數預計適用於任何類型的類Num。執行5.0 :: Double只是適用於一個類型,不適用於所有類型的,所以編譯器會抱怨。

的通用功能的一個例子是:

square :: (Num a) => a -> a 
square x = x * x 

這適用於任何類型這是一個Num。它適用於雙打,整數和任何其他你想使用的數字。因爲它可以有一個通用類型簽名,只需要參數Num。 (類型Num是必要的,因爲函數使用乘法*,這是在那裏定義的)

+0

+1 - 我們可以寫出上面的函數類型爲'FORALL一個。 Num a => a' - >它必須爲任何*類型工作*。 – Dario 2010-01-12 13:39:41

8

要添加到某物的答案:Haskell不是面向對象的。 DoubleNum的子類,因此如果您承諾返回多態性值Num(如同您可以在Java中那樣),則不能返回Double

當您編寫getN :: Num a => a時,您承諾返回一個在Num約束內完全多態的值。實際上,這意味着您只能使用Num類型的功能,例如+,*,-fromInteger

3

結賬存在量化類型

一個解決這個問題的方法是定義一個新的數據類型

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) ]