Biapplicative and Bimonad?

后端 未结 1 1176
误落风尘
误落风尘 2020-12-23 18:08

Haskell\'s Data.Bifunctor is basically:

class Bifunctor f where
  bimap :: (a -> c) -> (b -> d) -> f a b -> f c d 
相关标签:
1条回答
  • 2020-12-23 18:29

    A monad in category theory is an endofunctor, i.e. a functor where the domain and codomain is the same category. But a Bifunctor is a functor from the product category Hask x Hask to Hask. But we could try to find out what a monad in the Hask x Hask category looks like. It is a category where objects are pairs of types, i.e. (a, b), and arrows are pairs of functions, i.e. an arrow from (a, b) to (c, d) has type (a -> c, b -> d). An endofunctor in this category maps pairs of types to pairs of types, i.e. (a, b) to (l a b, r a b), and pairs of arrows to pairs of arrows, i.e.

    (a -> c, b -> d) -> (l a b -> l c d, r a b -> r c d)
    

    If you split this map function in 2, you'll see that an endofunctor in Hask x Hask is the same as two Bifunctors, l and r.

    Now for the monad: return and join are arrows, so in this case both are 2 functions. return is an arrow from (a, b) to (l a b, r a b), and join is an arrow from (l (l a b) (r a b), r (l a b) (r a b)) to (l a b, r a b). This is what it looks like:

    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)
    

    Or separated out:

    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
    

    And similar to m >>= f = join (fmap f m) we can define:

      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)
    

    Relative monads

    Recently, relative monads have been developed. A relative monad doesn't need to be an endofunctor! If we translate from the paper to Bifunctors in Haskell, you get:

    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
    

    Which defines a monad relative to the bifunctor j. If you pick j to be (,) you get your definition.

    The laws are the same as the monad laws:

    bireturn jab `bibind` k = k jab
    m `bibind` bireturn = m
    m `bibind` (\jab -> k jab `bibind` h) = (m `bibind` k) `bibind` h
    

    The first law prevents Maybe2 from being an instance, because bibind has to be able to extract both values from the result of bireturn.

    0 讨论(0)
提交回复
热议问题