如果我編譯以下源檔案ghc -Wall:
main = putStr . show $ squareOfSum 5
squareOfSum :: Integral a => a -> a
squareOfSum n = (^2) $ sum [1..n]
我得到:
powerTypes.hs:4:18: warning: [-Wtype-defaults]
? Defaulting the following constraints to type ‘Integer’
(Integral b0) arising from a use of ‘^’ at powerTypes.hs:4:18-19
(Num b0) arising from the literal ‘2’ at powerTypes.hs:4:19
? In the expression: (^ 2)
In the expression: (^ 2) $ sum [1 .. n]
In an equation for ‘squareOfSum’:
squareOfSum n = (^ 2) $ sum [1 .. n]
|
4 | squareOfSum n = (^2) $ sum [1..n]
| ^^
我了解 (^) 的型別是:
Prelude> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
這意味著它適用于任何a^b提供的ais aNum和bis an Integral。我也理解型別層次結構是:
Num --> Integral --> Int or Integer
where-->表示“includes”,前兩個是型別類,后兩個是型別。
為什么ghc不能最終推斷出它2是一個Int,而不是“將約束默認為整數”。為什么要ghc默認任何東西?正在取代2以2 :: Int一個很好的方法來解決此警告?
uj5u.com熱心網友回復:
在 Haskell 中,數字文字具有多型型別
2 :: Num a => a
這意味著該運算式2可用于生成任何數字型別的值。例如,所有這些運算式型別檢查:
2 :: Int
2 :: Integer
2 :: Float
2 :: Double
2 :: MyCustomTypeForWhichIDefinedANumInstance
從技術上講,每次使用時,2我們都必須撰寫2 :: T以選擇T我們想要的實際數字型別。幸運的是,這通常是不需要的,因為型別推斷可以經常T從背景關系中推斷出來。例如,
foo :: Int -> Int
foo x = x 2
在這里,x是Int因為型別注釋,并且 要求兩個運算元具有相同的型別,因此 Haskell 推斷2 :: Int. 從技術上講,這是因為( )具有型別
( ) :: Num a => a -> a -> a
然而,有時型別推斷不能T從背景關系中推斷出來。考慮這個涉及自定義型別類的示例:
class C a where bar :: a -> String
instance C Int where bar x = "Int: " show x
instance C Integer where bar x = "Integer: " show x
test :: String
test = bar 2
的價值是test什么?好吧,如果2是Int,那么我們有test = "Int: 2"。如果是Integer,那么我們有test = "Integer: 2"。如果它是另一種數字型別T,我們找不到 的實體C T。
這段代碼本質上是模棱兩可的。在這種情況下,Haskell的任務是不能被推斷是數字型別默認到Integer(程式員可以更改此默認為另一種型別,但它現在是不相關)。因此我們有test = "Integer: 2".
雖然這種機制使我們的代碼型別檢查,但它可能會導致一個意想不到的結果:據我們所知,程式員可能想要的2 :: Int。因此,GHC 選擇默認值,但會發出警告。
在您的代碼中,(^)可以使用任何Integral型別的指數。但是,在原則上,x ^ (2::Int)并x ^ (2::Integer)可能會導致不同的結果。我們知道情況并非如此,因為我們知道 的語意(^),但對于編譯器(^)來說,它只是一個具有該型別的隨機函式,它在Int和上的行為可能有所不同Integer。考慮,例如,
a ^ n = if n 3000000000 < 0 then 0 else 1
當n = 2,如果我們使用n :: Int的if后衛能在32位系統上是真實的。使用n :: Integer從不溢位的情況并非如此。
在這些情況下,標準解決方案是使用類似x ^ (2 :: Int).
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/370606.html
上一篇:帶正數的減法
