4

如果有人向我解釋下面的情況,我會非常感激。在我看來,好像Haskell準備在從函數返回值時執行某種整型強制。另一方面,我讀過Haskell從不隱式地轉換類型。不強制執行函數返回類型

如果我在GHCI鍵入:

> import Data.Word 
> let t :: (Integer, Word32); 
     t = let { y = fromIntegral (-1)  -- line breaks added for readability 
       ; y' :: Integer 
       ; y' = fromIntegral y } in (y', y) 

GHCI告訴我晚些時候t = (-1,4294967295)。但是,如果我特別限制當地y類型Word32

> let t :: (Integer, Word32); 
     t = let { y :: Word32 
       ; y = fromIntegral (-1)  -- line breaks added for readability 
       ; y' :: Integer 
       ; y' = fromIntegral y } in (y', y) 

GHCI會告訴我,t = (4294967295,4294967295)

我認爲,如果t的類型聲明explicite爲(Integer, Word32),GHCI會得出這樣的結論y' :: Integery :: Word32因爲函數的結果是(y', y)。然後,類型定義y :: Word32將是完全不必要的。

這一切都是在我試圖編寫函數以「安全地」在Integral類成員之間進行轉換時開始的 - 例如, Int - > Word32。當通過1Nothing時,該功能的意思是返回Just 1,當通過-1時。

通過SO和互聯網的簡短搜索沒有提供任何解釋。

回答

7

我認爲,如果t的類型聲明explicite爲(Integer, Word32),GHCI會得出這樣的結論y' :: Integery :: Word32因爲函數的結果是(y', y)

不,它不會推斷任何關於y'y的類型。它只是檢查它們是否與預期的類型兼容。一個簡單的例子:

x = -1 

y :: Integer 
y = x 

y' :: Word32 
y' = x 

x有哪些類型?它既不是Integer也不是Word32。這是type of literals

x :: Num a => a 
x = fromInteger (-1 :: Integer) 

而且Num a => a既與使用在y一個Integer,併爲Word32y'兼容。如何使用x並不重要,x的類型僅由該術語的定義方式決定。


來解釋你的結果,記得引用透明 - 我們就可以用自己的定義替換變量:

t = let y = fromIntegral (-1) 
     y' = (fromIntegral y) :: Integer 
    in (y', y) :: (Integer, Word32) 

擴展到

t = ((fromIntegral (fromIntegral (-1))) :: Integer -- nothing says Word32 here 
    , fromIntegral (-1) 
    ) :: (Integer, Word32) 

而第二

t = let y = (fromIntegral (-1)) :: Word32 
     y' = (fromIntegral y) :: Integer 
    in (y', y) :: (Integer, Word32) 

擴展到

t = ((fromIntegral ((fromIntegral (-1)) :: Word32)) :: Integer 
    , (fromIntegral (-1)) :: Word32 
    ) :: (Integer, Word32) 

1:我希望dreaded monomorphism restriction不惹我們。任何人都可以確認它不適用於x(或在什麼情況下)?

+1

難道不是因爲(來自整合:b - > c)。 (fromIntegral:a - > b):a - > c'不會導致類型錯誤?如果「中間」類型'b'既不是由輸入也不是由輸出決定的,它是如何挑選的? – gallais

+2

@gallais非常棒!解決方案是[數字類有一個特殊情況](https://www.haskell.org/onlinereport/decls.html#sect4.3.4),它允許編譯器默認'Num b => b'而不顯式類型註釋,默認的'default'是'Integer'。 – Bergi

+0

不錯!感謝您的解釋! – gallais

3

結果取決於-X[No]MonomorphismRestriction選項。默認情況下,在GHCi中使用-XNoMonomorphismRestriction選項,因此GHCi推斷爲y :: Num a => a的類型。並且在表達式fromIntegral y中它實例化爲Integer(默認情況下爲Num類),在表達式(y', y)中實例化爲Word32。當您明確指定類型y時,變量y在所有表達式中均爲Word32

如果運行命令:set -XMonomorphismRestriction,則所有變體都會得到相同的結果。