星号(种类,*)在这个Foldable实例中的作用

The role of the asterisks (kinds, *) in this Foldable instance

Foldable 文档中,我看到以下实例:

(Foldable f, Foldable g) => Foldable (Compose * * f g)

如果我查看 Compose 的定义,我发现它被声明为

newtype Compose f g a = Compose f (g a)

其中有种类 (* -> *) -> (* -> *) -> * -> *,对吧? (我想这是推断的)。现在据我所知,我想这样写是正确的:

(Foldable f, Foldable g) => Foldable (Compose f g)

因为Compose f g也有种* -> *。但是,我猜这两个 kind 标识符是有原因的。但是这是什么原因呢?

从技术上讲,如果您打开 PolyKindsCompose 的类型会更通用:

newtype Compose (f :: k -> *) (g :: k' -> k) (a :: k') = Compose (f (g a))

此类型由 PolyKinds 推断并需要它写入(并且它在 library 中如此定义 - 请注意 PolyKinds 在模块中启用)。

从技术上讲,这 Compose 有两个 kind 参数,它们是隐式的。这意味着您通常不会指定它们,通常也看不到它们。然而,黑线鳕的一个特点是它们确实显示了种类参数。但是如果你有兴趣,你可以在 GHCi 中看到同样的东西,例如

>:set -fprint-explicit-kinds
>import Data.Functor.Compose
>:i Compose
type role Compose nominal nominal representational nominal nominal
newtype Compose k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1)
  = Compose {getCompose :: f (g a)}
        -- Defined in `Data.Functor.Compose'
....
instance [safe] (Foldable f, Foldable g) =>
                Foldable (Compose * * f g)

请注意,Compose 有两种类型的参数 - ** - 因为 fg 必须属于类型 * -> * 由于 Functor 约束。