如果有耐心的人向我解释下面的情况,我将非常感激。在我看来,好像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
的类型明确表示为(Integer, Word32)
,GHCi会得出y' :: Integer
和y :: Word32
,因为函数结果为(y', y)
。然后,类型定义y :: Word32
将完全没必要。
当我尝试编写一个函数来“安全地”在Integral类成员之间进行转换时,这一切都开始了 - 例如Int - > Word32。该函数旨在通过Just 1
时传递1
,传递Nothing
时传递-1
。
通过搜索引擎优化和互联网进行的简短搜索并未向我提供任何解释。
答案 0 :(得分:7)
我认为如果
t
的类型明确表示为(Integer, Word32)
,GHCi会得出y' :: Integer
和y :: Word32
,因为函数结果为(y', y)
不,它没有推断出y'
和y
的类型。它只是检查它们是否与预期的类型兼容。一个更简单的例子 1 :
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
与Integer
中的y
和Word32
中的y'
兼容。使用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
(或在什么情况下)?