2017-01-21 21 views
0

我在看一些基本的類型類的實現:使用類型類實例時自動識別類型?

data Colour = Red | Green | Black 

class BasicEquality a where 
    isEqual :: a -> a -> Bool 

instance BasicEquality Bool where 
    isEqual True True = True 
    isEqual False True = True 
    isEqual True False = True 
    isEqual _ _   = False 

instance BasicEquality Colour where 
    isEqual Red Green = True 
    isEqual _ _   = False 

instance BasicEquality Int where 
    isEqual 100 100  = True 
    isEqual _ _   = False 

main = do 
    print $ isEqual Red Green //Output: True 
    print $ isEqual 100 100 //Output: Error Ambiguous type variable ‘a0’ arising from a use of ‘isEqual’ 

很明顯,但需要我特異性結合100這個工程時,我指定print $ isEqual (100 :: Int) (100 :: Int)

爲什麼Haskell的含蓄承認RedGreenColoursInt

+0

「基本平等」是一種非常奇怪的平等形式。 –

回答

3

Red等都是單態值,即他們有一個具體類型

Red :: Colour 

所以當Red在你的代碼輪番上漲,編譯器可以立即知道它是什麼類型,它可以使用此信息推斷什麼類型實例用於例如BasicEquality

OTOH,數字文字如100具有多態性類型Num a => a。原因是,我們希望能夠寫

Prelude> replicate 3 'q' 
"qqq" 

以及

Prelude> sqrt 3 
1.7320508075688772 

如果3有簡單類型Int,後者是行不通的,因爲sqrt需要一個類型的如Double。由於數字文字實際上是多態的,這並不重要。

您遇到的問題是isEqual也是多態。因此編譯器可以選擇多種不同的類型。圖片也有

instance BasicEquality Integer where 
    isEqual 50 1000  = True 
    isEqual _ _   = False 

然後isEqual 100 100可以被解釋爲isEqual (100 :: Int) 100(這是True)或isEqual (100 :: Integer) 100(哪個是假的)。

在實踐中,這是很少這麼大的一個問題,因爲你不會比較不同的數值文字(這些是已知的,所以你可以和簡單的硬編碼的結果!),但至多一個文字與您的程序中的一個變量相關聯,並且該變量通常會具有根據上下文確定的類型。例如,

*Main> let b = length "foobar" 
*Main> isEqual 4 b 
False 

沒有任何簽名的作品。