[英]Why does GHC needs a functional dependency to infer the type of this expression
[英]Why does GHC infer a monomorphic type here, even with MonomorphismRestriction disabled?
这是通过解析`f = f(<*>)pure`的类型来提示的,它讨论了一个更复杂的例子,但这个也有效。
以下定义编译没有问题:
w :: Integral a => a
w = fromInteger w
......当然,它在运行时并不起作用 ,但这不是问题所在。 关键是w
本身的定义使用w :: Integer
的专用版本 。 显然,这是一个合适的实例,因此是一个类型。
但是,如果我们删除签名,那么GHC不会推断出上述类型,而只会推断具体的类型:
w' = fromInteger w'
GHCi> :t w
w :: Integral a => a
GHCi> :t w'
w' :: Integer
好吧,当我看到这个时,我很确定这是工作中的单态限制。 众所周知,例如
i = 3
GHCi> :t i
i :: Integer
虽然i :: Num p => p
是完全可能的。 实际上,如果-XNoMonomorphismRestriction
是活动的,即如果禁用单态限制, 则推断i :: Num p => p
。
但是,在w'
情况下,即使禁用单态限制, 也仅推断出Integer
类型。
要指出这与默认有关:
fromFloat :: RealFrac a => Float -> a
q :: RealFrac a => a
q = fromFloat q
q' = fromFloat q'
GHCi> :t q
q :: RealFrac a => a
GHCi> :t q'
q' :: Float
为什么不推断出多态类型?
多态递归(函数调用自身的类型与调用它的类型不同) 总是需要类型签名。 完整的解释见Haskell 2010报告的第4.4.1节 :
如果定义变量
f
而未提供相应的类型签名声明,则在其自己的声明组外部使用f
(参见第4.5节 )将被视为具有相应的推断或主体类型。 但是,为了确保仍然可以进行类型推断,定义的出现以及其声明组中f
所有使用必须具有相同的单态类型(通过泛化获得主要类型,如第4.5.2节所述)。
后面的同一部分介绍了类型签名支持的多态递归示例。
我的理解是,在存在多态递归的情况下,无辅助类型推断通常是不可判定的,所以Haskell甚至都没有尝试过。
在这种情况下,类型检查器以
w :: a
其中a
是元变量。 由于fromInteger
在其自己的声明中被调用w
作为参数(因此在其声明组中),因此类型检查器将a
与Integer
统一起来。 没有变量可以概括。
由于同样的原因,对程序进行略微修改会产生不同的结果:
v = fromIntegral v
根据你原来的推理,Haskell会推断v :: forall a. Num a => a
v :: forall a. Num a => a
,默认RHS上的v
键入Integer
:
v :: forall a. Num a => a
v = fromIntegral (v :: Integer)
但相反,它以v :: a
开头。 由于v
传递给fromIntegral
,它强加Integral a
。 最后,它概括a
。 最终,程序结果是
v :: forall a. Integral a => a
v = fromIntegral (v :: a)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.