守卫是一个'vs'm()'

时间:2010-11-20 11:40:24

标签: haskell monads

guard :: (MonadPlus m) => Bool -> m ()
guard True  = return ()
guard False = mzero

Prelude Control.Monad> :t mzero
mzero :: (MonadPlus m) => m a

guard的假分支中,mzero的类型为m a,但guard的返回类型已指定为m ()。因此我不太明白为什么编译器不会抱怨这个。

我的意思是,如果mzero返回一个类型为Maybe Int的值,这当然与Maybe ()不同,对吗?

2 个答案:

答案 0 :(得分:6)

编译器不会抱怨,因为m am ()的超集。

答案 1 :(得分:0)

mzero :: (MonadPlus m) => m a的类型对于forall (a :: *) (m :: * -> *). MonadPlus m => m a来说有点简短,这意味着任何选择类型构造函数m并输入a },如果仅满足mMonadPlus类型类的实例的限制,则mzero可以是该类型。

guard的类型同样为forall (m :: * -> *). MonadPlus m => Bool -> m ()。在guard False = mzero中,右侧的mzero类型必须为m ()才能选择m。选择a()m作为请求的monad,mzero的类型,其本身就变为m (),这正是guard {1}}需要返回。