GHCi 可以告诉你各种各样的事情。例如,如果您输入:
data T f g = T (f String Int) (g Bool)
在一个文件Kinds.hs
中,您可以将其加载到 GHCi 中并询问以下内容T
:
> :l Kinds.hs
> :k T
T :: (* -> * -> *) -> (* -> *) -> *
>
所以看起来 GHCi 同意你的解决方案。
对于您的第一个问题,您不能要求 GHCi 直接告诉您 kind of f
,但由于f
是 typeclass 的参数C
,您可以要求 kind of C
:
> :k C
C :: (* -> * -> *) -> Constraint
>
意思是C
需要一种类型* -> * -> *
来产生约束。所以,GHCi 不同意你的观点,并认为这f
是善意的* -> * -> *
。
查看类型签名:
comp :: f b c -> f a b -> f a c
请注意,您不能拥有f
kind (* -> *) -> * -> *
,因为f b c
这意味着那b
是 kind* -> *
而f a b
意味着 that b
of kind *
,并且不能两者兼而有之。
事实证明,最普遍的可能类型是:
f :: k -> k -> *
其中前两个参数被迫具有相同的种类,因为在k
两个位置b
(分别使用 inf a b
和有意义。f b c
*
f b c
f a b
f a c
comp
但是,Haskell98(无扩展)不会推断出最一般的可能种类,因此它选择k
be *
,给出种类签名* -> * -> *
。事实证明,如果您启用某个扩展 ( PolyKinds
),则将k -> k -> *
改为使用 kind 签名。