2017-02-11 31 views
0

可能有人請解釋爲什麼這編譯設置類型爲NUM

Prelude> 1 :: Num a => a 

這並不

Prelude> 1.0 :: Num a => a 

第二個例子將與Fractional工作,但NumFractional超。就像它的超類Integral

回答

4

如果我們有

x :: Num a => a 

x用戶可以選擇a通緝。例如。

x :: Int 

如果x = 1.5不適用?

因爲這個原因浮點文字不能給多態類型Num a => a,因爲它的值不會(通常)適合所有類型的所有Num

積分文字適合每種數字類型,因此它們是允許的。

+0

謝謝@chi。當你這樣做時有意義:)所以'1 :: Num a => a'適用於任何'Num'實例的'a',但'1.0'不適用。 – rodic

+1

@rodic是的。從理論上講,Haskell的設計者可能已經強制要求'1.0'被當作'1'來處理,但實際上,發現在給定的上下文中'1.0'類型檢查但是'1.5'確實會引起混亂不。因此,只允許使用'1.0'來代表'Fractional'類型中的類型值。 – chi

+0

是的,當我寫1.0時,我有任何想法。但現在我意識到我的原始問題可以重寫,爲什麼'1 :: a'不能編譯。非常感謝您的幫助。 – rodic

3

類型類之間的超類關係確實是而不是在類型之間建立關係。它告訴我們,只有,如果類型T是類型類Ç的一員,並是一個超類的Ç,然後也將的成員。

說每個值v ::噸可以在任何類型的,這也是的構件使用。但這就是你要說的:

3.14159 :: Num a => a 
3

區分OO語言中的多態和Haskell中的多態是很重要的。 OO polymorphism is covariant, while Haskell's parametric polymorphism is contravariant

這意味着:在面向對象的語言,如果你有

class A {...} 
class B: A {...} 

AB一個超類,然後B類型的任何值也A類型的值。 (請注意,任何特定的其實並不多態的,但有一個具體的類型!)因此,如果你有

class Num {...} 
class Fractional: Num {...} 

那麼Fractional值確實可以被用作Num值。這大致是協變意味着什麼:任何子類值is also a superclass value;值的層次結構與類型層次結構相同。

在Haskell中,class es是不同的。沒有「Num類型的值」這樣的東西,只有具體類型的值a類型可能在Num類。

不像在面向對象的語言,如1 :: Num a => a多態:它可以在任何類型的環境的需求,提供的類型在Num類。 (其實這句法只是縮寫1 :: ∀ a . Num a => a,將被解讀爲「爲所有類型的a,你可以有a類型的值1。)例如,

Prelude> let x = 1 :: Num a => a 
Prelude> x :: Int 
1 
Prelude> x :: Double 
1.0 

你也可以給x更具體的約束Fractional,因爲這是Num的一個子類。這只是限制什麼類型的多態值可以被實例:

Prelude> let x = 1 :: Fractional a => a 
Prelude> x :: Int 

<interactive>:6:1: 
    No instance for (Fractional Int) arising from a use of ‘x’ 
    ... 
Prelude> x :: Double 
1.0 

因爲Int不是小數類型。因此,Haskell的多態性是逆變的:限於超類的多態值也可以被限制到一個子類,而不是相反的方式。具體而言,可以很明顯的有

Prelude> let y = 1.0 :: Fractional a => a 

y相同x'),但你不能一概而論這y' = 1.0 :: Num a => a。 Ingo評論說這是一件好事,否則將有可能做

Prelude> 3.14159 :: Int 
    ???? 
+0

明白了。 num不是類似於oo的類型,而是一組類型,爲了val是多態的,它必須能夠實例化爲任何num類型,任何其他規則都會導致荒謬的情況,正如你們所展示的那樣。 – rodic