'Kind' 对类型索引的 GADT 中的 forall 感到困惑

'Kind' of confused about forall in type-indexed GADTs

我 运行 在 GHC 8.0.1 中遇到了一个奇怪的情况,使用种类索引(?)GADT,在类型与种类签名中引入 foralls 会产生不同的类型检查行为。

考虑以下数据类型:

{-# LANGUAGE TypeInType, GADTs, ExplicitForAll #-}
-- Same thing happens when we replace ExplicitForAll with ScopedTypeVariables

import Data.Kind

data F (k :: * -> *) where

data G :: F k -> * where
  G :: G x

这种数据类型编译得很好。但是,如果我们想在构造函数G中指定x的种类,我们会得到一个类型错误。

data H :: F k -> * where
  H :: forall k' (x :: F k'). H x

错误信息是

• Kind variable ‘k’ is implicitly bound in datatype
  ‘H’, but does not appear as the kind of any
  of its type variables. Perhaps you meant
  to bind it (with TypeInType) explicitly somewhere?
• In the data declaration for ‘H’

如果我们将forall添加到kind签名中(在构造函数中有或没有forall),没有错误。

data I :: forall k. F k -> * where
  I :: I x

data J :: forall k. F k -> * where
  J :: forall k' (x :: F k'). J x

怎么回事?

TypeInType 的作者在这里。 K. A. Buhr 就在上面得到了它;这只是一个错误。它固定在 HEAD 中。

对于过度好奇的人:此错误消息旨在消除像

这样的定义
data J = forall (a :: k). MkJ (Proxy a)

哪里

data Proxy (a :: k) = Proxy

可以从 Data.Proxy 导入。当在 Haskell98 风格的语法中声明一个数据类型时,任何存在量化的变量都必须用 forall 显式地引入范围。但是 k 从来没有明确地进入范围;只是用在a的那种。所以这意味着 k 应该被普遍量化(换句话说,它应该是 J 的不可见参数,就像 Proxyk 参数一样)......但是那么当我们写J的时候,就没有办法确定k应该是什么,所以总是模棱两可的。 (相比之下,我们可以通过查看 a 的类型来发现 k 参数到 Proxy 的选择。)

J 的定义在 8.0.1 和 HEAD 中是不允许的。