'm' 'против' m () 'в охране - PullRequest
       0

'm' 'против' m () 'в охране

2 голосов
/ 20 ноября 2010
guard :: (MonadPlus m) => Bool -> m ()
guard True  = return ()
guard False = mzero

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

В ветви False guard тип mzero равен m a, но тип возврата guard указан как m (). Поэтому я не совсем понимаю, почему компилятор не будет жаловаться на это.

Я имею в виду, если mzero возвращает значение, набранное как Maybe Int, что, конечно, отличается от Maybe (), верно?

Ответы [ 2 ]

6 голосов
/ 20 ноября 2010

Компилятор не будет жаловаться, потому что m a является надмножеством m ().

0 голосов
/ 03 января 2016

Тип mzero :: (MonadPlus m) => m a является сокращением для forall (a :: *) (m :: * -> *). MonadPlus m => m a, что означает для любой выбор конструктора типа m и типа a, если только ограничение, m экземпляр класса MonadPlus удовлетворен, mzero может иметь этот тип.

Тип guard аналогично равен forall (m :: * -> *). MonadPlus m => Bool -> m (). Таким образом, в guard False = mzero тип mzero с правой стороны должен быть m () для любого подходящего выбора m. Выбрав a в качестве () и m в качестве запрошенной монады, тип mzero сам по себе становится m (), и это именно то, что guard должно вернуть.

...