GHCi是否不使用默认声明来解决类型歧义?

3
作为一个对Haskell相对较新的人,我正在努力理解以下差异(我相信有很好的原因)。 也许我的问题仅源于对GHCi的误解,但当我能够消除疑虑时,晚上我会睡得更好。
下面是问题。如果在脚本中将名称“foo”绑定到某个整数表达式(这里仅为“1”)并编译该脚本后,在GHCi中加载后,使用“:t”命令告诉我“foo”的类型是“Integer”。
$ printf %s\\n "foo=1" > foo.hs
$ ghci
λ> :l foo.hs
[1 of 1] Compiling Main             ( foo.hs, interpreted )
Ok, modules loaded: Main.
λ>  :t foo
foo :: Integer

据我理解,foo 的类型的不确定性是通过一些默认声明得到解决的,我推测这些声明在 Prelude 中某处被指定。
default (Integer, Double)

到目前为止,一切都很好。然而,当我在 GHCi 中直接执行一个看似等价的 let 绑定时,:t 告诉我后者仍将 foo 视为多态数值常量,而不是一个 Integer

$ ghci
λ> let foo=1
λ> :t foo
foo :: Num a => a

这种差异应该怎样解释?背后的理论基础是什么?GHCi是否未应用默认声明来解决类型歧义?如果它确实这样做了,在什么情况下会这样做?(供参考,我使用的是GHC 7.8.3版本。)
1个回答

4
在 GHC 7.8 及以上版本中,GHCi shell 中确实关闭了单态化限制 Monomorphism Restriction,因此交互式 shell 中的声明不会将 Num 默认规则应用于不在 lambda 绑定器下的顶级表达式(根据单态化限制)。但是单态化限制仍然适用于被加载的外部模块。
您可以使用 :set -XMonomorphismRestriction 来切换此设置。

谢谢。我已经擅自添加了一个链接到Haskell 2010报告的相关部分,这是由于您的回答而发现的。 - jub0bs
2
默认规则在某些情况下仍然适用(我无法确定具体是哪些情况)。例如,show 1将默认1Integer。单态限制放宽只是避免不必要地应用这些默认值。 - dfeuer
@dfeuer 重新排列了措辞,希望更清晰一些。 - Stephen Diehl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接