可能有人請解釋爲什麼這編譯設置類型爲NUM
Prelude> 1 :: Num a => a
這並不
Prelude> 1.0 :: Num a => a
第二個例子將與Fractional
工作,但Num
是Fractional
超。就像它的超類Integral
。
可能有人請解釋爲什麼這編譯設置類型爲NUM
Prelude> 1 :: Num a => a
這並不
Prelude> 1.0 :: Num a => a
第二個例子將與Fractional
工作,但Num
是Fractional
超。就像它的超類Integral
。
如果我們有
x :: Num a => a
的x
用戶可以選擇a
通緝。例如。
x :: Int
如果x = 1.5
不適用?
因爲這個原因浮點文字不能給多態類型Num a => a
,因爲它的值不會(通常)適合所有類型的所有Num
。
積分文字適合每種數字類型,因此它們是允許的。
類型類之間的超類關係確實是而不是在類型之間建立關係。它告訴我們,只有,如果類型T是類型類Ç的一員,並乙是一個超類的Ç,然後噸也將乙的成員。
它不說每個值v ::噸可以在任何類型的,這也是乙的構件使用。但這就是你要說的:
3.14159 :: Num a => a
區分OO語言中的多態和Haskell中的多態是很重要的。 OO polymorphism is covariant, while Haskell's parametric polymorphism is contravariant。
這意味着:在面向對象的語言,如果你有
class A {...}
class B: A {...}
即A
是B
一個超類,然後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
????
明白了。 num不是類似於oo的類型,而是一組類型,爲了val是多態的,它必須能夠實例化爲任何num類型,任何其他規則都會導致荒謬的情況,正如你們所展示的那樣。 – rodic
謝謝@chi。當你這樣做時有意義:)所以'1 :: Num a => a'適用於任何'Num'實例的'a',但'1.0'不適用。 – rodic
@rodic是的。從理論上講,Haskell的設計者可能已經強制要求'1.0'被當作'1'來處理,但實際上,發現在給定的上下文中'1.0'類型檢查但是'1.5'確實會引起混亂不。因此,只允許使用'1.0'來代表'Fractional'類型中的類型值。 – chi
是的,當我寫1.0時,我有任何想法。但現在我意識到我的原始問題可以重寫,爲什麼'1 :: a'不能編譯。非常感謝您的幫助。 – rodic