Biapplicative和Bimonad?

Lan*_*dei 29 monads haskell

Haskell Data.Bifunctor基本上是:

class Bifunctor f where
  bimap :: (a -> c) -> (b -> d) -> f a b -> f c d 
Run Code Online (Sandbox Code Playgroud)

我也能找到一个Biapply.我的问题是,为什么不存在完整的双层次结构(层次结构?),如:

class Bifunctor f => Biapplicative f where
  bipure :: a -> b -> f a b
  biap :: f (a -> b) (c -> d) -> f a c -> f b d 

class Biapplicative m => Bimonad m where
  bibind :: m a b -> (a -> b -> m c d) -> m c d

  bireturn :: a -> b -> m a b
  bireturn = bipure

bilift :: Biapplicative f => (a -> b) -> (c -> d) -> f a c -> f b d
bilift f g = biap $ bipure f g 

bilift2 :: Biapplicative f => (a -> b -> c) -> (x -> y -> z) -> f a x -> f b y -> f c z
bilift2 f g = biap . biap (bipure f g)
Run Code Online (Sandbox Code Playgroud)

Pair是这些的一个实例:

instance Bifunctor (,) where
  bimap f g (x,y) = (f x, g y)

instance Biapplicative (,) where
  bipure x y = (x,y)
  biap (f,g) (x,y) = (f x, g y)

instance Bimonad (,) where
  bibind (x,y) f = f x y
Run Code Online (Sandbox Code Playgroud)

和...类型

data Maybe2 a b = Fst a | Snd b | None
--or 
data Or a b = Both a b | This a | That b | Nope
Run Code Online (Sandbox Code Playgroud)

...... IMO也会有实例.

没有足够的匹配类型吗?或者是关于我的代码存在严重缺陷?

Sjo*_*her 26

类别理论中的monad是一个endofunctor,即一个functor,其中domain和codomain是同一类别.但是Bifunctor从产品类别的函子Hask x HaskHask.但我们可以尝试找出该Hask x Hask类别中的monad是什么样的.它是一个类别,其中对象是成对的类型,即(a, b)箭头是一对函数,即箭头从(a, b)(c, d)具有类型(a -> c, b -> d).此类别中的endofunctor映射对类型对类型,即(a, b),以(l a b, r a b)和对箭头到双箭头所示,即

(a -> c, b -> d) -> (l a b -> l c d, r a b -> r c d)
Run Code Online (Sandbox Code Playgroud)

如果将此map函数拆分为2,则会看到endofunctor Hask x Hask与两个Bifunctors 相同,l并且r.

现在对于monad: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)
Run Code Online (Sandbox Code Playgroud)

或者分开:

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
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

相对单子

最近,相关的单子已经开发出来.相对monad不需要是endofunctor!如果我们从BifunctorHaskell 的论文翻译成s,你会得到:

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
Run Code Online (Sandbox Code Playgroud)

它定义了一个相对于bifunctor的monad j.如果你选择j(,)你得到你的定义.

法律与monad法律相同:

bireturn jab `bibind` k = k jab
m `bibind` bireturn = m
m `bibind` (\jab -> k jab `bibind` h) = (m `bibind` k) `bibind` h
Run Code Online (Sandbox Code Playgroud)

第一定律阻止Maybe2成为实例,因为bibind必须能够从结果中提取两个值bireturn.

  • 你可以这样做,但是你没有范畴论意义上的单子:https://en.wikipedia.org/wiki/Monad_(category_theory) (2认同)