Монады — это не что иное, как аппликативный функтор с некоторыми дополнительными функциями. Это класс Type, который управляет тремя основными правилами, известными как монадические правила .
Все три правила строго применимы к объявлению Монады, которое выглядит следующим образом:
class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b x >> y = x >>= \_ -> y fail :: String -> m a fail msg = error msg
Три основных закона, которые применимы к декларации Монады:
-
Left Identity Law — функция возврата не меняет значение и не должна ничего менять в монаде. Это может быть выражено как «return> => mf = mf».
-
Правильный закон идентификации — функция возврата не меняет значение и не должна ничего менять в монаде. Это может быть выражено как «mf> => return = mf».
-
Ассоциативность — Согласно этому закону, и Functors, и экземпляр Monad должны работать одинаково. Это может быть математически выражено как «(f> ==> g)> => h = f> => (g> = h)».
Left Identity Law — функция возврата не меняет значение и не должна ничего менять в монаде. Это может быть выражено как «return> => mf = mf».
Правильный закон идентификации — функция возврата не меняет значение и не должна ничего менять в монаде. Это может быть выражено как «mf> => return = mf».
Ассоциативность — Согласно этому закону, и Functors, и экземпляр Monad должны работать одинаково. Это может быть математически выражено как «(f> ==> g)> => h = f> => (g> = h)».
Первые два закона повторяют одну и ту же точку, т. Е. Возврат должен иметь одинаковое поведение по обе стороны от оператора связывания .
Мы уже использовали много монад в наших предыдущих примерах, не осознавая, что они монады. Рассмотрим следующий пример, где мы используем монаду списка для генерации определенного списка.
main = do print([1..10] >>= (\x -> if odd x then [x*2] else []))
Этот код выдаст следующий вывод —