32

HaskellData.Bifunctorは基本的に次のとおりです。

class Bifunctor f where
  bimap :: (a -> c) -> (b -> d) -> f a b -> f c d 

私も見つけることができBiapplyました。私の質問は、なぜ次のような完全な二重階層(bierarchy?)がないのかということです。

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)

ペアはこれらのインスタンスです:

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にもインスタンスがありますか。

一致するタイプが十分ではありませんか?それとも私のコードに関する何かがひどく欠陥がありますか?

4

1 に答える 1

28

圏論のモナドはエンドファンクター、つまりドメインと終域が同じカテゴリーであるファンクターです。しかし、aBifunctorは製品カテゴリ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に分割すると、のエンド関数が2つのs、およびとHask x Hask同じであることがわかります。Bifunctorlr

モナドの場合:returnjoinは矢印なので、この場合は両方とも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)

相対モナド

最近、相対モナドが開発されました。相対的なモナドは、エンドファンクターである必要はありません!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

これは、bifunctorに関連するモナドを定義し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ため、インスタンスになることを防ぎます。bibindbireturn

于 2012-11-26T16:24:44.773 に答える