Haskell的Data.Bifunctor
基本上是:
class Bifunctor f where
bimap :: (a -> c) -> (b -> d) -> f a b -> f c d
我也可以找到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)
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
类似......
data Maybe2 a b = Fst a | Snd b | None
--or
data Or a b = Both a b | This a | That b | Nope
...... IMO也会有实例。
没有足够的匹配类型吗?或者是关于我的代码存在严重缺陷的事情?
答案 0 :(得分:24)
类别理论中的monad是一个endofunctor,即一个functor,其中domain和codomain属于同一类别。但Bifunctor
是从产品类别Hask x Hask
到Hask
的仿函数。但我们可以尝试找出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)
如果你在2分割此地图功能,你会看到,在一个endofunctor Hask x Hask
是相同的2 Bifunctor
S,l
和r
。< / p>
现在对于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)
或分开:
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)
最近,relative monads已经开发出来。相对monad不需要是endofunctor!如果我们从Haskell中的论文翻译成Bifunctor
,你会得到:
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
它定义了一个相对于bifunctor j
的monad。如果您选择j
为(,)
,则会得到您的定义。
法律与monad法律相同:
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
的结果中提取这两个值。