开发者

'm a' vs 'm ()' in guard

开发者 https://www.devze.com 2023-01-25 21:13 出处:网络
guard :: (MonadPlus m) => Bool开发者_开发知识库 -> m () guard True= return () guard False = mzero
guard :: (MonadPlus m) => Bool开发者_开发知识库 -> m ()
guard True  = return ()
guard False = mzero

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

In the False branch of guard, the type of mzero is m a, but the return type of guard has been specified as m (). Hence I don't quite get it why compiler won't complain about this.

I mean if mzero returns a value typed as Maybe Int, which is, of course, different from Maybe (), right?


The compiler won't complain because m a is a superset of m ().


The type of mzero :: (MonadPlus m) => m a is a bit of short-hand for forall (a :: *) (m :: * -> *). MonadPlus m => m a, meaning for any choice of type constructor m and type a, if just the restriction that m is an instance of the MonadPlus typeclass is satisfied, mzero can be at that type.

The type of guard, similarly, is forall (m :: * -> *). MonadPlus m => Bool -> m (). In guard False = mzero, the type of the mzero on the right-hand side must thus be m () for any appropriate choice of m. By choosing a to be () and m to be the requested monad, mzero's type, itself becomes m () which is exactly what guard needs to return.

0

精彩评论

暂无评论...
验证码 换一张
取 消