Haskell:模式匹配类型注释中需要ScopedTypeVariables

时间:2015-04-01 15:48:31

标签: haskell types type-variables

为什么此代码需要ScopedTypeVariables扩展名?

{-# LANGUAGE ScopedTypeVariables #-}

char = case Just '3' of 
    Just (x :: Char) -> x
    Nothing          -> '?'

当我阅读ScopedTypeVariables上的文档时,它似乎意味着将函数体中的类型变量与父函数签名统一起来。这段代码片段并没有统一任何类型的变量!

加载ScopedTypeVariables而不加载ExplicitForAll会产生什么影响? ScopedTypeVariables的所有其他用例似乎都需要ExplicitForAll才能实际运行。但在上面的代码段中,没有ExplicitForAll

1 个答案:

答案 0 :(得分:4)

ScopedTypeVariables自动启用ExplicitForAll为了您的理智,我建议在使用任何其他类型系统扩展时始终使用ScopedTypeVariables(除了可能仅处理类/实例/上下文并且从不直接使用ExplicitForAll

模式变量签名需要ScopedTypeVariables的原因只是这些签名是扩展的一部分。在其他用途​​中,它们为您提供了一种将类型变量引入范围的方法。例如:

f (Just (x::a)) = bob
  where
    bob::[a]
    bob = [x]

我不知道为什么模式签名本身是ScopedTypeVariables的一部分;很可能它们是为此目的而创建的,并且所有代码都是一次性编写的。将它们分开以进行正交扩展几乎肯定被认为比它的价值更麻烦。

修改

实际上,有一个很好的理由。除了模式绑定之外,模式签名中的类型变量是通用的,将该变量放入范围。因此,在上面的示例中,您不需要知道外部类型环境中是否存在a。如果您可以启用没有作用域类型变量的模式签名,则可以根据是否打开作用域类型变量来扩展或不扩展该变量。对于没有ExplicitForAll的{​​{1}},会出现同样的混淆,这就是为什么我要杀死该扩展程序并将ScopedTypeVariables设置为默认值,或者至少使用扩展程序自动启用它目前启用ScopedTypeVariables