考虑以下程序(在 Haskell 中,但可以是任何 HM 推断语言):
x = []
y = x!!0
使用 HM(或通过运行编译器),我们推断:
x :: forall t. [t]
y :: forall a. a
我理解这是如何发生的,按照通常的泛化/实例化规则进行操作,但我不确定是否需要像forall a. a
.
一个问题是:由于我们在这里有一个越界访问,因此可以排除该程序作为有效示例的可能性。相反,我们可以说我们推断的通用类型是程序中出现问题的标志吗?如果是,我们是否可以利用这个“事实”在其他情况下故意不检查无效程序?
下一个程序得到更奇怪的类型:
c = []
d = (c!!0) + (1 :: Int)
推断类型:
c :: forall t. [t]
d :: Int
...虽然d
是从c
!
我们能否在不排除有效程序的情况下增加 HM 以在这里做得更好?
编辑:我怀疑这是使用部分函数的工件(!!0
在这种情况下)。但请看:
c = []
d = case c of [] -> 0; (x:_) -> x + (1 :: Int)
现在没有使用偏函数。然而,c :: forall t. [t]
和d :: Int
。