2010-11-20 1 views
2
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(), правильно?

ответ

6

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

+0

'mzero' может возвращать что-то вроде 'Maybe Int', правильно? Я думаю, что это отличается от «Maybe()» – aXqd

+1

@aXqd: для монады Maybe, 'mzero = Nothing', которая не имеет предпочтительного типа для' a'. Если вы действительно наложили 'Nothing' на' Maybe Int', оно отличается от 'Maybe()'. Тем не менее, тип 'Maybe a' для любого возможного' a', а не 'Maybe Int', поэтому' Maybe() 'действителен. – kennytm

+0

@KennyTM Спасибо за ваш ответ. Да, я могу использовать плохой пример. Однако, если я напишу собственный тип - «MyType», а затем сделаю его экземпляром «Monad» и «MonadPlus». Я могу сделать mzero 'return' MyType Int '. На самом деле, я думаю, если есть вероятность, что то, что будет возвращено «mzero», не является «m()», компилятор должен жаловаться на это. Поскольку тип «mzero» и тип возврата «guard» не совпадают друг с другом. Я знаю, что я ошибаюсь в этом заключении. Я просто не знаю, где проблема. : P – aXqd

0

Типа 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.

+0

Это был тип 'guard'. Теперь это 'guard :: Alternative f => Bool -> f()'. Я считаю, что новый ответ должен отражать новый тип. – dfeuer

+0

Мое редактирование, однако, было только исправлением. – dfeuer

 Смежные вопросы

  • Нет связанных вопросов^_^