Arrows
カテゴリによって一般化され、型クラスによって一般化されCategory
ます。
class Category f where
(.) :: f a b -> f b c -> f a c
id :: f a a
Arrow
型クラス定義はスーパーCategory
クラスとして持っています。カテゴリ (haskell の意味で) は関数を一般化します (作成することはできますが、適用することはできません)。したがって、カテゴリは間違いなく「計算のモデル」です。 タプルを操作するための追加の構造をArrow
提供します。Category
つまり、Category
Haskell の関数空間に関するものをミラー化しながら、Arrow
それをプロダクト タイプに関するものに拡張します。
EveryMonad
は "Kleisli カテゴリ" と呼ばれるものを生成し、この構造により のインスタンスが得られますArrowApply
。完全に一周しても行動が変わらないようにMonad
、任意のものから を構築できます。したがって、深い意味では、 と は同じものです。ArrowApply
Monad
ArrowApply
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
instance Monad m => Category (Kleisli m) where
id = Kleisli return
(Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)
instance Monad m => Arrow (Kleisli m) where
arr f = Kleisli (return . f)
first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))
実際には、すべてArrow
がスーパークラスApplicative
に加えて(種類を正しくするために普遍的に定量化された)を生成し、適切なとCategory
の組み合わせがあなたのを再構築するのに十分であると信じています. Category
Applicative
Arrow
ですから、これらの構造は深く結びついています。
警告: 先に気まぐれな解説があります。Functor
/ Applicative
/Monad
考え方とCategory
/考え方の中心的な違いの 1 つArrow
は、 whileとその同類がオブジェクト(Haskell の型)Functor
のレベルでの一般化であり、 /は射の概念の一般化 ( Haskell の関数) であるということです。一般化された射のレベルでの思考は、一般化されたオブジェクトのレベルでの思考よりも高いレベルの抽象化を伴うと私は信じています。それが良いこともあれば、そうでないこともあります。一方で、カテゴリカルな根拠があり、数学の誰も考えていないという事実にもかかわらずCategory
Arrow
Arrows
Applicative
興味深いです。Applicative
一般的に よりもよく理解されているのは私の理解ですArrow
。
基本的には「Category < Arrow < ArrowApply」「Functor < Applicative < Monad」「Category ~ Functor」「Arrow ~ Applicative」「ArrowApply ~ Monad」と考えることができます。
より具体的な以下:
計算をモデル化するための他の構造について: カテゴリ構造の「矢印」(ここでは射を意味するだけ) の方向を逆にして、「双対」または「共同構造」を得ることができます。したがって、モナドが次のように定義されている場合
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
(まあ、それは Haskell が物事を定義する方法ではないことはわかっていますがma >>= f = join $ fmap f ma
、join x = x >>= id
そうである可能性もあります) その場合、コモナドは次のようになります。
class Functor m => Comonad m where
extract :: m a -> a -- this is co-return
duplicate :: m a -> m (m a) -- this is co-join
これもかなり一般的であることが判明しました。それがセルオートマトンComonad
の基本的な構造であることがわかりました。完全を期すために、エドワード・クメットがファンクターと「拡張可能なファンクター」の間のクラスに入れていることを指摘する必要があります。Control.Comonad
duplicate
Comonad
extend :: (m a -> b) -> m a -> m b -- Looks familiar? this is just the dual of >>=
extend f = fmap f . duplicate
--this is enough
duplicate = extend id
Monad
すべての s も「拡張可能」であることが判明しました
monadDuplicate :: Monad m => m a -> m (m a)
monadDuplicate = return
すべてComonads
が「参加可能」ですが
comonadJoin :: Comonad m => m (m a) -> m a
comonadJoin = extract
したがって、これらの構造は非常に接近しています。