我读过的Haskell教程有一节介绍类型kinds的基础知识,并描述了一个类型类
class Tofu t where
tofu :: j a -> t a j
有种类
* -> (* -> *) -> *
我理解这一点,但当我在GHCi中输入:k Tofu
时,我得到了
Tofu :: (* -> (* -> *) -> *) -> GHC.Prim.Constraint
什么是GHC.Prim.Constraint
以及为什么Tofu
有这种形式而不仅仅是* -> (* -> *) -> *
?
答案 0 :(得分:6)
t
是类Tofu
的类* -> (* -> *) -> *
的类型参数(写为t :: * -> (* -> *) -> *
)。
这是GHC推断的t
类型,因为在没有-XPolyKinds
的情况下,GHC会尝试将所有类型参数默认为类*
。因此,GHC假设a
具有*
种类(尽管您的签名中没有任何内容使其成为唯一的选择)。
类型构造函数(->)
具有种类 * -> * -> *
。由于j a
作为(->)
的参数显示,j a
必须有*
种。由于GHC假设a
有*
种类,j
是一种类型*
并返回某种类型*
的类型。因此:
j :: * -> *
由于t
同时应用于a
和j
,t
的{{1}}类型为* -> (* -> *) -> *
,因为第一个参数a
具有种类*
和第二个参数j
有*->*
种,t a j
的整体类型必须有*
种,因为它也是类型为(->)
的参数。
类只是采用类型参数的类型(就像data Foo a b
),除了Foo a b
有*
种类,而Tofu t
有类型Constraint
。因此Tofu
的种类是:
(* -> (* -> *) -> *) -> Constraint
如GHC所示, Constraint
只是给予约束的那种。在签名
(Num a) => a -> a -> a
(Num a)
是种类的类型 Constraint
。