为什么在禁用MonomorphismRestriction的情况下,GHC仍会在此处推断单态类型? [英] Why does GHC infer a monomorphic type here, even with MonomorphismRestriction disabled?

查看:152
本文介绍了为什么在禁用MonomorphismRestriction的情况下,GHC仍会在此处推断单态类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是由提示的提示f = f(< *)| pure` ,它讨论了一个更复杂的示例,但是这个示例也可以工作.

This was prompted by Resolving the type of `f = f (<*>) pure`, which discusses a more complicated example, but this one works too.

以下定义可以毫无问题地编译:

The following definition compiles without problem:

w :: Integral a => a
w = fromInteger w

...当然,它在运行时不会起作用,但这只是问题所在.关键是w本身的定义使用 w :: Integer的专用版本.显然, 是合适的实例,因此进行类型检查.

...Of course it doesn't work runtime-wise, but that's beside the question. The point is that the definition of w itself uses a specialised version of w :: Integer. Clearly that is a suitable instantiation, and therefore typechecks.

但是,如果我们删除签名,那么GHC不会推断出上述类型,而只会推断出具体的类型:

However, if we remove the signature, then GHC infers not the above type, but only the concrete one:

w' = fromInteger w'

GHCi> :t w
w :: Integral a => a
GHCi> :t w'
w' :: Integer

好吧,当我看到这一点时,我相当确定这是工作中的单态性限制.众所周知,例如

Well, when I saw this, I was fairly sure this was the monomorphism restriction at work. It's well known that also e.g.

i = 3

GHCi> :t i
i :: Integer

尽管i :: Num p => p是完全可能的.实际上,如果-XNoMonomorphismRestriction处于活动状态,即禁用了同构限制,则推断出i :: Num p => p .

although i :: Num p => p would be perfectly possible. And indeed, i :: Num p => p is inferred if -XNoMonomorphismRestriction is active, i.e. if the monomorphism restriction is disabled.

但是,在w'的情况下,即使禁用了单态限制 ,也只能推断出Integer类型.

However, in case of w' only the type Integer is inferred even when the monomorphism restriction is disabled.

要计算出这与默认设置有关:

To count out that this has something to do with defaulting:

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

为什么不能推断多态类型?

Why is the polymorphic type not inferred?

推荐答案

多态递归(其中函数以与调用时不同的类型调用自身)总是需要类型签名.完整的解释位于该文档的第4.4.1节 Haskell 2010年报告:

Polymorphic recursion (where a function calls itself at a different type than the one at which it was called) always requires a type signature. The full explanation is in Section 4.4.1 of the Haskell 2010 Report:

如果在未提供相应类型签名声明的情况下定义了变量f,则每次在其声明组之外使用f(请参见第4.5.2节).

If a variable f is defined without providing a corresponding type signature declaration, then each use of f outside its own declaration group (see Section 4.5) is treated as having the corresponding inferred, or principal type. However, to ensure that type inference is still possible, the defining occurrence, and all uses of f within its declaration group must have the same monomorphic type (from which the principal type is obtained by generalization, as described in Section 4.5.2).

稍后,同一部分将提供类型签名支持的多态递归示例.

The same section later presents an example of polymorphic recursion supported by a type signature.

我的理解是,在存在多态递归的情况下,通常无法确定无助的类型推断,因此Haskell甚至不会尝试.

My understanding is that unaided type inference is generally undecidable in the presence of polymorphic recursion, so Haskell doesn't even try.

在这种情况下,类型检查器以

In this case, the type checker starts with

w :: a

其中,a是元变量.由于fromInteger在其自身的声明中(因此也在其声明组中)以w作为参数调用,因此类型检查器将aInteger统一.没有要概括的变量.

where a is a meta-variable. Since fromInteger is called with w as an argument within its own declaration (and therefore within its declaration group), the type checker unifies a with Integer. There are no variables left to generalize.

由于相同的原因,对程序进行少量修改会产生不同的结果:

A slight modification of your program gives a different result for the same reason:

v = fromIntegral v

根据您的原始推理,Haskell会推断v :: forall a. Num a => a,默认情况下,RHS上的v键入Integer:

By your original reasoning, Haskell would infer v :: forall a. Num a => a, defaulting the v on the RHS to type Integer:

v :: forall a. Num a => a
v = fromIntegral (v :: Integer)

但是,它以v :: a开头.由于v传递给fromIntegral,因此强加了Integral a.最后,它概括了a.最后,程序变成了

But instead, it starts with v :: a. Since v is passed to fromIntegral, it imposes Integral a. Finally, it generalizes a. In the end, the program turns out to be

v :: forall a. Integral a => a
v = fromIntegral (v :: a)

这篇关于为什么在禁用MonomorphismRestriction的情况下,GHC仍会在此处推断单态类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆