[英]Addition of 2 + 2.8 in Haskell
表達式2 + 2.8
在Haskell中有效並且評估為4.8
與C類似,其涉及稱為類型提升的東西,Haskell使用類型推斷和adhoc多態來獲得結果。
問題是什么原因,它不是兩種語言中弱類型的例子。
“弱打字”和“強打字”在某種程度上是主觀的,合理的人們往往不同意他們的意思。
在C中,你有2個類型為int
,2.8有類型為double
。 當你計算2 + 2.8
,會應用“通常的算術轉換”,這會將int
提升為double
。 所以你得到這個:
((double) 2) + 2.8
這會將2(一個int
)轉換為double
。 結果是double
類型。
在Haskell中,沒有隱式轉換。 在Haskell中發生的是2的類型為Num a => a
而2.8的類型為Fractional a => a
。 因此,2 + 2.8具有類型Fractional a => a
。
然而,這是一個問題,因為Fractional a => a
是多態的。 您可以將其視為一個多參數函數,它接受零參數。 傳入一個類型,函數會生成該類型的值。
所以你可以這樣做:
2 + 2.8 :: Rational
或者你可以這樣做:
2 + 2.8 :: Double
你會得到不同的答案。 當你編寫2 + 2.8 :: Rational
,2是Rational
,2.8是Rational
,整個結果是Rational
。 當你寫2 + 2.8 :: Double
,那么2是Double
,2.8是Double
,結果是Double
。 你沒有獲得轉換。
您可以這樣想:在Haskell中,類型檢查器知道結果具有類型T,因此輸入也具有類型T. 在C中,類型檢查器不會像那樣“向前看”,所以它必須在臨時的基礎上轉換類型。
當你做這樣的事情時,這更明顯:
1 / 2 + 0.0
在C中,這將給你0.0,因為1 / 2
是整數除法。 在Haskell中,這將給你0.5,因為一切都將使用Double
或Rational
或你選擇的任何東西完成。 這是Haskell和C之間的一個非常重要的區別,它通常是人們說“強”或“弱”打字時的意思(即,當他們甚至可以就這意味着什么達成一致時)。
所以在C中,你得到:
(double) ((int) 1 / (int) 2) + (double) 0.0
// ^^^ intermediate result stays in int
在Haskell中,你得到:
(1 :: Double) / (2 :: Double) + (0.0 :: Double)
如果你想在Haskell中使用類似C的行為,你最終會得到:
fromIntegral (1 `quot` 2 :: Int) + 0.0 :: Double
2
是Haskell中的任何數字類型的多態。 2
在C中不是完全多態的。
相反,請嘗試在兩個語言中更明確地說明您的類型:
float test()
{
int i = 2;
float f = 2.8;
return (f+i);
}
VS
test :: Float
test = (2 :: Int) + (2.8 :: Float)
怎么了?
Haskell中沒有類型提升,否則(2::Int) + (2::Double)
是合法的。 相反, 文字 2
類型為Num a => a
,這意味着它可以被視為具有實例Num
的任何類型的值 。
但是,交互式解釋器中存在類型默認值 。 像show 2
這樣的表達式(如果你試圖顯示像2
這樣的簡單表達式,則會隱式調用它)是不明確的; 解釋器不知道是否返回"2"
或"2.0"
或某些其他字符串值,該值對於作為Num
實例的類型有效。 而不是強制用戶通過show 2 :: Integer
指定類型,解釋器只是選擇一個默認類型Integer
用於其他多態值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.