簡體   English   中英

在Haskell中添加2 + 2.8

[英]Addition of 2 + 2.8 in Haskell

表達式2 + 2.8在Haskell中有效並且評估為4.8與C類似,其涉及稱為類型提升的東西,Haskell使用類型推斷和adhoc多態來獲得結果。

問題是什么原因,它不是兩種語言中弱類型的例子。

“弱打字”和“強打字”在某種程度上是主觀的,合理的人們往往不同意他們的意思。

C

在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,因為一切都將使用DoubleRational或你選擇的任何東西完成。 這是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM