9

如果我检查我kind得到Maybe这个:

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

Monad现在,如果我检查我得到的那种:

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

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

4

2 回答 2

12

不像MaybeMonad不是类型;它是一个类型类

其他类型类也是如此:

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

where*表示具体类型(如Boolor Int),->表示更高种类的类型(如Maybe),并Constraint表示类型约束的思想。这就是为什么:


正如我们所知,我们不能做这样的签名:

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

因为Monad应该用作约束,也就是说,'这必须是一个单子才能工作':

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

我们这样做是因为我们知道它return不能在任何旧类型上工作m,所以我们return在名称下定义了不同类型的行为Monad。换句话说,没有单一的东西可以称为 Monad,而只有行为可以称为 Monadic。

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


Maybe是 的一个实例Monad。这意味着在某个地方,有人写道:

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

...并定义了Maybe应如何表现为 Monad。这就是为什么我们可以使用Maybe带有前缀约束的函数或类型Monad m => ...。这本质上是定义由 应用的约束的地方Monad

于 2015-04-08T08:57:09.043 回答
8

ConstraintShow Int是, Monad Maybe, 和的种类Monoid [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
于 2015-04-08T09:00:23.570 回答