Ответ 1
Монада в теории категорий является эндофункцией, т.е. функтором, где область и кодомен имеют одну и ту же категорию. Но a Bifunctor
является функтором из категории продуктов Hask x Hask
до Hask
. Но мы могли бы попытаться выяснить, как выглядит монада в категории Hask x Hask
. Это категория, где объекты представляют собой пары типов, т.е. (a, b)
, а стрелки - это пары функций, то есть стрелка от (a, b)
до (c, d)
имеет тип (a -> c, b -> d)
. Энтундуктор в этой категории отображает пары типов в пары типов, т.е. От (a, b)
до (l a b, r a b)
, а пары стрелок - к парам стрелок, т.е.
(a -> c, b -> d) -> (l a b -> l c d, r a b -> r c d)
Если вы разделите эту функцию карты на 2, вы увидите, что endofunctor в Hask x Hask
совпадает с двумя Bifunctor
s, l
и r
.
Теперь для монады: return
и join
являются стрелками, поэтому в этом случае обе являются 2-мя функциями. return
- стрелка от (a, b)
до (l a b, r a b)
, а join
- стрелка от (l (l a b) (r a b), r (l a b) (r a b))
до (l a b, r a b)
. Это выглядит так:
class (Bifunctor l, Bifunctor r) => Bimonad l r where
bireturn :: (a -> l a b, b -> r a b)
bijoin :: (l (l a b) (r a b) -> l a b, r (l a b) (r a b) -> r a b)
Или выделено:
class (Bifunctor l, Bifunctor r) => Bimonad l r where
bireturnl :: a -> l a b
bireturnr :: b -> r a b
bijoinl :: l (l a b) (r a b) -> l a b
bijoinr :: r (l a b) (r a b) -> r a b
И подобно m >>= f = join (fmap f m)
, мы можем определить:
bibindl :: l a b -> (a -> l c d) -> (b -> r c d) -> l c d
bibindl lab l r = bijoinl (bimap l r lab)
bibindr :: r a b -> (a -> l c d) -> (b -> r c d) -> r c d
bibindr rab l r = bijoinr (bimap l r rab)
Относительные монады
В последнее время были разработаны относительные монады. Относительная монада не обязательно должна быть эндофуктором! Если мы переведем из статьи в Bifunctor
в Haskell, вы получите:
class RelativeBimonad j m where
bireturn :: j a b -> m a b
bibind :: m a b -> (j a b -> m c d) -> m c d
Определяет монаду относительно бифунтера j
. Если вы выберите j
как (,)
, вы получите свое определение.
Законы те же, что и законы монады:
bireturn jab `bibind` k = k jab
m `bibind` bireturn = m
m `bibind` (\jab -> k jab `bibind` h) = (m `bibind` k) `bibind` h
Первый закон запрещает Maybe2
быть экземпляром, потому что bibind
должен иметь возможность извлекать оба значения из результата bireturn
.