有没有理由我们不能使用DataKinds填充类型?

时间:2014-06-26 20:27:01

标签: haskell data-kinds

使用DataKinds,像

这样的定义
data KFoo = TFoo

引入了KFoo :: BOX种类型和TFoo :: KFoo类型。为什么我不能继续定义

data TFoo = CFoo

这样CFoo :: TFooTFoo :: KFooKFoo :: BOX

所有构造函数是否都必须属于属于*类型的类型?如果是这样,为什么?

编辑:执行此操作时我没有收到错误,因为构造函数和类型共享命名空间,但GHC允许冲突,因为它将名称歧义为常规类型,而不是提升构造函数。文档说使用'作为前缀来引用提升的构造函数。当我将第二行更改为

data 'TFoo = CFoo

我收到错误

  

格式错误的类型或类声明:TFoo

2 个答案:

答案 0 :(得分:9)

  

所有构造函数是否都属于属于*类型的类型?

是。这正是*的意思:它是(提升/盒装,我从未确定过那部分)Haskell类型的那种。事实上,尽管它们共享type语法,但所有其他类型都不是真正的类型。相反,*是类型的元类型级别类型,而所有其他类型都是元类型级别的类型,用于不属于类型但不是类型构造函数或完全不同的东西。

(同样,还有一些关于未装箱类型的东西;那些肯定是类型但我认为data构造函数不可能。)

答案 1 :(得分:6)

  

所有构造函数是否都属于属于类型*的类型?如果是这样,为什么?

它们必须属于*(或#)类型的最重要原因是GHC使用的相分离:DataKinds在编译期间被擦除。我们可以通过定义单例GADT数据类型来间接表示它们的运行时:

{-# LANGUAGE DataKinds #-}

data Nat = Z | S Nat

data SNat n where
   SZ :: SNat Z
   SS :: SNat n -> SNat (S n)

但是DataKind索引本身仍然不存在运行时。各种类型为相位分离提供了一个简单的规则,对于相关类型来说这并不是那么简单(尽管它可能会极大地简化类型级编程)。