使用DataKinds,像
这样的定义data KFoo = TFoo
引入了KFoo :: BOX
种类型和TFoo :: KFoo
类型。为什么我不能继续定义
data TFoo = CFoo
这样CFoo :: TFoo
,TFoo :: KFoo
,KFoo :: BOX
?
所有构造函数是否都必须属于属于*
类型的类型?如果是这样,为什么?
编辑:执行此操作时我没有收到错误,因为构造函数和类型共享命名空间,但GHC允许冲突,因为它将名称歧义为常规类型,而不是提升构造函数。文档说使用'
作为前缀来引用提升的构造函数。当我将第二行更改为
data 'TFoo = CFoo
我收到错误
格式错误的类型或类声明:TFoo
答案 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
索引本身仍然不存在运行时。各种类型为相位分离提供了一个简单的规则,对于相关类型来说这并不是那么简单(尽管它可能会极大地简化类型级编程)。