作用域类型变量需要明确foralls。 为什么?(Scoped type variables r

2019-08-19 09:13发布

如果你想使用GHC的词法作用域类型变量 ,你也必须使用明确的全称量化 。 也就是说,你必须添加forall声明到你的函数的类型签名:

{-# LANGUAGE ExplicitForAll, ScopedTypeVariables #-}

f :: forall a . [a] -> [a]      -- The `forall` is required here ...
f (x:xs) = xs ++ [x :: a]       -- ... to relate this `a` to the ones above.

这实际上有什么用定量,还是扩展作家只是笼络了forall关键字作为新的,更广泛的适用范围界定,其中一个方便的标记?

换句话说,我们为什么不能离开了forall像往常一样? 那岂不是很清楚的是,在函数体内注释类型变量指向同一个名字的变量函数签名? 还是会打字以某种方式存在问题或不明确?

Answer 1:

是的,量词是有意义的,需要的类型变得有意义。

首先要注意的是真的没有这样的事情在Haskell一个“无法量化”的类型签名。 没有签名forall真的隐含量化。 此代码...

f :: [a] -> [a]                         -- No `forall` here ...
f (x:xs) = xs ++ [x :: a]               -- ... or here.

......真正的意思是:

f :: forall a . [a] -> [a]              -- With a `forall` here ...
f (x:xs) = xs ++ [x :: forall a . a]    -- ... and another one here.

因此,让我们弄清楚这是什么说。 重要的是要注意到,命名的类型变量a在签名fx是由单独的量词约束。 这意味着,他们是不同的变量,尽管共享一个名字。 所以上面的代码是相同的:

f :: forall a . [a] -> [a]
f (x:xs) = xs ++ [x :: forall b . b]    -- I've changed `a` to `b`

随着分化的名字,它现在不仅表明在签名的类型变量fx是无关的,但是,对于签名x声称, x可以是任何类型的。 但是,这是不可能的,因为x必须具有绑定到特定类型的af被施加到一个参数。 的确类型检查器将拒绝此代码。

在另一方面,与单一forall在签名f ...

f :: forall a . [a] -> [a]              -- A `forall` here ...
f (x:xs) = xs ++ [x :: a]               -- ... but not here.

...的a在上的签名x是通过在开头的量词结合f的类型签名,所以此a表示相同的类型由被称为变量表示的类型af的签名。



文章来源: Scoped type variables require explicit foralls. Why?