Традиции монады традиционно описываются в терминах >>=
и pure
:
pure a >>= k = k a
m >>= pure = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
Однако, монады также могут быть определены в терминах join
вместо >>=
. Я хотел бы придумать формулировку законов монады в терминах join
.
Используя x >>= f = join (fmap f x)
, его легко переписать существующие законы монады, чтобы устранить >>=
. Упрощая результаты с помощью прикладных законов, первые два закона довольно приятно выражены:
join . pure = id
join . fmap pure = id
Интуиция для этих законов также проста, так как ясно, что введение дополнительного "слоя" с pure
должно быть no-op в сочетании с join
. Однако третий закон не так хорош. Он выглядит следующим образом:
join (fmap (\x -> join (fmap h (k x))) m)
= join (fmap h (join (fmap k m)))
Это не приятно уменьшает использование прикладных законов, и его гораздо труднее понять, не глядя на него какое-то время. У него, конечно же, нет такой же легкой интуиции.
Существует ли эквивалентная альтернативная формулировка законов монады в терминах join
, которую легче понять? В качестве альтернативы, есть ли способ упростить вышеупомянутый закон или облегчить его поиск? Версия с >>=
уже менее приятна, чем версия, выраженная композицией Kleisli, но версия с join
почти нечитаема.