3.2 KiB
title | localeTitle |
---|---|
Monad | монада |
Законы Монад
Существует 3 правила, которые ещё называются законами, которым должны удовлетворять те типы данных, которые хотят быть монадами (на самом деле, это не совсем так, мы можем создать тип, который будет в хаскеле монадой, но не соответствовать законом. Это не запрещено, но очень не приветствуется)
Левая единица (Left Identity)
return a >>= f
= f a
Здесь говорится о том, что если мы берём значение и возвращаем его в контексте (заключаем его в монаду),
а затем используем >>=
для передачи его в функцию, то эта операция - то же самое, что и
прменение этой функции к исходному значению.
Правая единица (Right Identity)
m >>= return
= m
А тут говорится о том, что когда мы используем >>=
для передачи монадического (заключённого) значения
в функцию return
, мы получаем изначальное монадическое (заключённое) значение.
Ассоциативность (Associativity)
(m >>= f) >>= g
= m >>= (\x -> f x >>= g)
Этот закон позволяет нам связывать вызовы монадических функций не смотря на их вложенность.
Это может показаться очевидным, и Вы можете подумать, что так и должно быть, но на самом деле ассоциативность обязательна для такого поведения.
Так что на счёт >>=
и return
?
Всё просто:
>>=
, или 'bind' берёт монаду и функцию, которая принимает на вход чистое значение
и возвращает монаду, после этого применяет эту функцию к монаде. Это позволяет нам
работать с данными внутри монады, которые не могут быть по-другому доступы другим,
немонадическим функциям.
return
, с другой стороны, берёт некое значение и возвращает монаду, содержащую
это значение. Наверное, всё, что вы хотели бы знать про return
, её тип:
return :: a -> m a
Монада Maybe
justHead :: Maybe Char
justHead = do
(x:xs) <- Just ""
return x
Монада List
возвращает тоже самое значение, что и функция pure
для класса типов Applicative
экземпляр Monad [], где
return x = [x]
xs >> = f = concat (map f xs)
fail _ = []