在Haskell中,类型的“类型”称为Kinds,表示为*
。如:
Maybe :: * -> *
Either :: * -> * -> *
我想知道Haskell或其他强类型语言中的“类型”类型是否有任何等价物?
它们是否具有实际意义?是否有任何案例证明它们非常有用?
任何对某些材料的提及都将不胜感激。
答案 0 :(得分:8)
从GHC 8开始,作为在Haskell中向依赖类型迈进的一部分,有一个新的扩展-XTypeInType
使得类型的“类型”成为......类型。
启用TypeInType
时,语言中只有两个级别:术语和类型。类型级别会自行折叠,因此类型的“类型”(在Haskell术语中,“kind”)也是一种类型。
Prelude> :set -XTypeInType
Prelude> import Data.Kind
Prelude Data.Kind> :k Int
Int :: *
Prelude Data.Kind> :k (*)
(*) :: *
同样Type
成为*
的同义词,Prelude Data.Kind> :k (Int :: *)
(Int :: *) :: *
Prelude Data.Kind> :k (Int :: Type)
(Int :: Type) :: *
Prelude Data.Kind> :k (Monad :: (Type -> Type) -> Constraint)
(Monad :: (Type -> Type) -> Constraint) :: (* -> *) -> Constraint
是在术语级别具有实际值的类型:
evt.getSource().getTitle()
这使你可以使用类型已经存在的所有machinery种类,以inconsistent from a logical perspective为代价丰富Haskell对类型级恶作剧的支持(这无关紧要因为Haskell已经存在由于其他原因而被视为证据制度的“不一致”。)
答案 1 :(得分:7)
在Haskell中,类型的“类型”称为Kinds,表示为
*
。如:
这不正确。 *
是类型,即类型级实体的类型,表示可能的运行时值的集合†。
kind 这个词有点像cludge。它只是需要因为Haskell(有充分理由,不能少!)在编译时和运行时之间有明显的区别。 值仅存在于运行时,其他所有内容仅在编译时存在。特别是,这些值的类型仅存在于编译时。
现在,也需要对类型进行分类,就像需要对类型中的值进行分类一样。原则上,没有理由不像任何其他值那样考虑类型,因此具有类型的类型。这几乎是依赖类型语言的基本思想,如Idris或Agda ¶。
在Haskell中,这并不完全有效:由于前面提到的运行时/编译时区别,你不能在一个封闭的‡中抛出类型和值。因此,种类的概念:这些也是类型,但它们的类型不同于值,在编译时也像种类本身一样存在,而不是像运行时那样存在于值中。
这意味着没有必要从类型中提升另一个级别,因为没有比编译时更早的级别。 (除非你在游戏中带上模板Haskell;不知道是否还有人考虑过这样的问题。)
† 它们不是真正的集合,但是有点(双关语无意)。
从某种意义上来说,‡ 已关闭:您可以谈论......类型的类型,而且从不真正需要发明任何新东西。子>
¶ 据我所知,Agda仍然区分类型,类型等(Set_2
等)。但我相信这更多地与Agda是总语言这一事实有关。不过我在这里可能是错的。
答案 2 :(得分:2)