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,则所有变体都会得到相同的结果。