为什么这段代码需要 ScopedTypeVariables
扩展?
{-# LANGUAGE ScopedTypeVariables #-}
char = case Just '3' of
Just (x :: Char) -> x
Nothing -> '?'
当我阅读有关ScopedTypeVariables
的文档时,它似乎意味着将函数体中的类型变量与父函数签名统一起来。不过,此代码片段并未统一任何类型变量!
此外,加载 ScopedTypeVariables
而不同时加载 ExplicitForAll
有什么影响? ScopedTypeVariables
的所有其他用例似乎都需要 ExplicitForAll
才能实际工作。但是在上面的代码片段中,没有 ExplicitForAll
。
最佳答案
ScopedTypeVariables
自动启用 ExplicitForAll
为了您的理智,我建议在使用任何其他类型系统扩展时始终使用 ScopedTypeVariables
那些只处理类/实例/上下文的)并且从不直接使用 ExplicitForAll
。
模式变量签名需要 ScopedTypeVariables
的原因只是此类签名是扩展的一部分。在其他用途中,它们为您提供了一种将类型变量引入作用域的方法。例如:
f (Just (x::a)) = bob
where
bob::[a]
bob = [x]
我不知道为什么模式签名本身是 ScopedTypeVariables
的一部分;它们很可能是为此目的而创建的,并且所有代码都是一次性编写的。将它们分开以进行正交扩展几乎肯定被认为比它的值(value)更麻烦。
编辑
事实上,这是有充分理由的。除了模式绑定(bind)之外,模式签名中的类型变量被泛化,将该变量带入作用域。所以在上面的例子中,你不需要知道外部类型环境中是否有a
。如果您可以在没有作用域类型变量的情况下启用模式签名,则可以根据是否启用作用域类型变量来泛化或不泛化该变量。对于没有 ScopedTypeVariables
的 ExplicitForAll
也会发生同样的混淆,这就是为什么我想取消该扩展并将 ScopedTypeVariables
设置为默认值,或者至少使用当前启用 ExplicitForAll
的扩展自动打开它。
关于Haskell:模式匹配类型注释中需要ScopedTypeVariables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29395265/