Мне всегда нравилось следующее интуитивное объяснение власти монады относительно функтора: монада может изменять форму; функтор не может.
Например: length $ 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. Я хотел бы, чтобы моя любимая фраза "Монад может изменить форму", просто прикосновение более честное; если необходимо.