什么是约束实物签名

What is Constraint in kind signature

如果我检查 Maybekind 我得到这个:

λ> :k Maybe
Maybe :: * -> *

现在,如果我检查 Monad 的类型,我会得到:

λ> :k Monad
Monad :: (* -> *) -> Constraint

那里有什么 Constraint 以及为什么需要它?为什么不只是这个 * -> * ?

Maybe不同,Monad不是类型;它是一个 typeclass.

其他类型类也是如此:

Num :: * -> Constraint
Functor :: (* -> *) -> Constraint
Bifunctor :: (* -> * -> *) -> Constraint

其中*表示具体类型(如BoolInt),->表示更高级的类型(如Maybe), Constraint 表示类型约束的概念。这就是为什么:


据我们所知,我们不能做出这样的签名:

return :: a -> Monad a -- This is nonsense!

因为Monad应该作为一个约束,也就是说,'this must be a monad to work':

return :: (Monad m) => a -> m a

我们这样做是因为我们知道 return 不能在任何旧类型 m 上工作,所以我们在名称 [=] 下为不同的类型定义 return 的行为15=]。也就是说,没有单一的事物可以称为Monad,只有行为可以称为Monadic。

出于这个原因,我们创建了这个类型约束,说我们必须预先定义一些东西作为 Monad 才能使用这个功能。这就是为什么Monad的种类是(* -> *) -> Constraint——它本身不是一个类型!


MaybeMonad 的实例。这意味着在某个地方,有人写道:

instance Monad Maybe where
  (>>=) = ... -- etc

...并定义了 Maybe 应该如何作为 Monad。这就是为什么我们可以将 Maybe 用于具有前缀约束 Monad m => ... 的函数或类型。这基本上是定义 Monad.

应用的约束的地方

Constraint 是那种例如Show IntMonad MaybeMonoid [a]。大致就是类型注解中=>左边可以出现的那种

现在

Show Int :: Constraint

Int是一种类型,即

Int :: *

我们可以为 Show 分配一个函数类型,如下所示

Show :: * -> Constraint
             ^-- the result kind
        ^-- the kind of Int

在你的例子中,恰好 Monad 接受了像 Maybe 这样的参数,所以

Maybe Int :: *
Maybe :: * -> *
Monad :: (* -> *) -> Constraint
                     ^-- the result kind
         ^-- the kind of Maybe