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

3
为什么这段代码需要使用ScopedTypeVariables扩展?
{-# LANGUAGE ScopedTypeVariables #-}

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

当我阅读 ScopedTypeVariables 的文档时,它似乎意味着将函数体中的类型变量与父函数签名统一。然而,这段代码片段并没有统一任何类型变量!
另外,如果加载了 ScopedTypeVariables,但没有同时加载 ExplicitForAll,会有什么影响?所有其他 ScopedTypeVariables 的用例似乎都需要 ExplicitForAll 才能实际工作。但在上面的代码片段中,没有 ExplicitForAll
1个回答

5

ScopedTypeVariables可以自动启用ExplicitForAll。为了您的心智健康,我建议在使用任何其他类型系统扩展时(除了可能只涉及类/实例/上下文的扩展),始终使用ScopedTypeVariables,而不直接使用ExplicitForAll

ScopedTypeVariables之所以需要用于模式变量签名,只是因为此类签名是该扩展的一部分。除了其他用途外,它们还为您提供了一种将类型变量引入作用域的方法。例如:

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

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

编辑

实际上,有一个非常好的理由。除了模式绑定外,模式签名中的类型变量是泛化的,将该变量引入作用域。因此,在上面的例子中,您不需要知道外部类型环境中是否有a。如果可以在没有范围类型变量的情况下启用模式签名,则根据是否打开了范围类型变量,变量可以泛化或不泛化。同样的混淆也会发生在没有ScopedTypeVariablesExplicitForAll,这就是为什么我想消除该扩展并使ScopedTypeVariables成为默认值,或者至少在当前启用ExplicitForAll的扩展时自动打开它。


为什么模式变量签名需要ScopedTypeVariables呢?直到这个扩展出现之前,这是不可能的吗?在这种情况下,它们似乎是正交的,因为没有任何类型变量的统一,因为表达式中没有类型变量。 - CMCDragonkai
@CMCDragonkai,看到我的编辑了吗?我怀疑这并没有什么深刻的原因,但我也不是很确定。 - dfeuer
我明白了。在你的例子中,a 是普遍量化的吗?还是从其他地方引入的? - CMCDragonkai
通过扩展,模式(x :: a)在其作用域中定义了a,其类型为x的类型。 @CMCDragonkai - Ørjan Johansen
2
实际上,GHC 6.8.1是第一个具有“LANGUAGE”预处理系统的版本,它同时拥有“ScopedTypeVariables”和“PatternSignatures”。后者在7.0.1中从文档中删除,尽管您仍然可以提供它并获得一个弃用警告,告诉您改用“ScopedTypeVariables”。 - Ørjan Johansen
@ØrjanJohansen 啊,那很有道理。你的评论应该被提升。 - CMCDragonkai

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