'类'在类型索引的GADT中混淆forall

时间:2016-12-10 01:22:28

标签: haskell types ghc

我在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

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

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添加到种类签名(在构造函数中有或没有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

发生了什么?

1 个答案:

答案 0 :(得分:3)

此处TypeInType的作者。 K. A. Buhr在正确的上方得到它;这只是一个bug。它已在HEAD中修复。

对于过于好奇:此错误消息旨在消除类似

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

,其中

data Proxy (a :: k) = Proxy

可以从Data.Proxy导入。在使用Haskell98样式语法声明数据类型时,必须使用forall将任何存在量化的变量明确地放入范围。但k从未明确地纳入范围;它仅用于a种类。这意味着k应该被普遍量化(换句话说,它应该是J的不可见参数,例如k Proxy}的参数...但是然后当我们写J时,无法确定k应该是什么,所以它总是不明确的。 (相反,我们可以通过查看k类型来发现Proxy参数对a的选择。)

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