Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top