我正在阅读的Haskell教程有一节介绍了类型类型的基础知识,并描述了一个类型类
class Tofu t where
tofu :: j a -> t a j
的类型
* -> (* -> *) -> *
我明白,但是当我在GHCi中输入:k Tofu
时,我得到
Tofu :: (* -> (* -> *) -> *) -> GHC.Prim.Constraint
什么是GHC.Prim.Constraint
?为什么Tofu
有这种形式而不是简单的* -> (* -> *) -> *
?
t
是* -> (* -> *) -> *
类(写为t :: * -> (* -> *) -> *
)的Tofu
类的类型参数。这是GHC推断的t
类型,因为在没有-XPolyKinds
的情况下,GHC尝试将所有类型参数默认为*
类型。因此,GHC假设a
具有*
类型(尽管您的签名中没有任何内容使这成为唯一的选择)。
(->)
具有类型 * -> * -> *
。因为j a
是作为(->)
的参数出现的,所以j a
的类型必须是*
。由于GHC假定a
具有*
类型,因此j
是一个接受*
类型的东西并返回*
类型的东西的类型。因此:j :: * -> *
由于t
同时应用于a
和j
,因此t
的类型为* -> (* -> *) -> *
,因为第一个参数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
。