Мне всегда нравилось следующее интуитивное объяснение мощности монады относительно функтора: монада может изменять форму; функтор не может.
Например: длина $ fmap f [1,2,3]
всегда равна 3
.
Однако для монады length $ [1,2,3] >> = g
часто не равно 3
. Например, если g
определяется как:
g :: (Num a) => a -> [a]
g x = if x==2 then [] else [x]
, то [1,2,3] >> = g
равно [1,3]
.
Что меня немного беспокоит, так это сигнатура типа g
. Кажется невозможным определить функцию, которая изменяет форму ввода, с универсальным монадическим типом, например:
h :: (Monad m, Num a) => a -> m a
Классы типов MonadPlus или MonadZero имеют соответствующие нулевые элементы, которые можно использовать вместо []
, но теперь у нас есть кое-что больше, чем монада.
Я прав? Если да, то есть ли способ передать эту тонкость новичку в Haskell. Я хотел бы сделать мою любимую фразу «монады могут менять форму», чуть более честно; если нужно.