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