「モナドはエンドファンクターの範疇にある単なるモノイドである」という定義は、正しいとはいえ、始めるには不適切です。これは主に冗談を意図したブログ投稿からのものです。しかし、通信に興味がある場合は、Haskell でデモンストレーションできます。
カテゴリの一般的な記述は、オブジェクトとオブジェクト間のモーフィズムの抽象的なコレクションです。カテゴリ間のマッピングはファンクターと呼ばれ、オブジェクトをオブジェクトに、射を射に連想的にマップし、同一性を保持します。エンドファンクタは、カテゴリからそれ自体へのファンクタです。
{-# LANGUAGE MultiParamTypeClasses,
ConstraintKinds,
FlexibleInstances,
FlexibleContexts #-}
class Category c where
id :: c x x
(.) :: c y z -> c x y -> c x z
class (Category c, Category d) => Functor c d t where
fmap :: c a b -> d (t a) (t b)
type Endofunctor c f = Functor c c f
いわゆる自然性条件を満たすファンクター間のマッピングは、自然変換と呼ばれます。Haskell では、これらは型の多相関数です: (Functor f, Functor g) => forall a. f a -> g a
.
圏上のモナドは、エンドファンクター、恒等ファンクターのC
3 つである。Mu と eta は、三角形恒等式と結合性恒等式を満たす 2 つの自然な変換であり、次のように定義されます。(T,η,μ)
T
1
C
Haskellμ
では isjoin
とη
isreturn
return :: Monad m => a -> m a
join :: Monad m => m (m a) -> m a
Haskell での Monad のカテゴリ定義は、次のように記述できます。
class (Endofunctor c t) => Monad c t where
eta :: c a (t a)
mu :: c (t (t a)) (t a)
これらからバインド演算子を導出できます。
(>>=) :: (Monad c t) => c a (t b) -> c (t a) (t b)
(>>=) f = mu . fmap f
これは完全な定義ですが、同等に、モナドの法則がファンクター カテゴリを持つモノイドの法則として表現できることも示すことができます。オブジェクトをファンクター (つまり、カテゴリー間のマッピング) として持ち、自然な変換 (つまり、ファンクター間のマッピング) を射として持つカテゴリーである、このファンクター カテゴリーを構築できます。エンドファンクターのカテゴリーでは、すべてのファンクターは同じカテゴリー間のファンクターです。
newtype CatFunctor c t a b = CatFunctor (c (t a) (t b))
これにより、写像合成としてのファンクター合成を持つカテゴリが生じることを示すことができます。
-- Note needs UndecidableInstances to typecheck
instance (Endofunctor c t) => Category (CatFunctor c t) where
id = CatFunctor id
(CatFunctor g) . (CatFunctor f) = CatFunctor (g . f)
モノイドには通常の定義があります。
class Monoid m where
unit :: m
mult :: m -> m -> m
関手の圏上のモノイドは単位 a としての自然な変換と、自然な変換を組み合わせた乗算演算を持ちます。Kleisli 合成は、乗法を満たすように定義できます。
(<=<) :: (Monad c t) => c y (t z) -> c x (t y) -> c x (t z)
f <=< g = mu . fmap f . g
したがって、「モナドはエンドファンクターのカテゴリのモノイドにすぎない」ということになります。これは、エンドファンクターおよび (mu, eta) からのモナドの通常の定義の「ポイントフリー」バージョンにすぎません。
instance (Monad c t) => Monoid (c a (t a)) where
unit = eta
mult = (<=<)
少し代入すると、 のモノイド特性が(<=<)
、モナドの自然な変換の三角形と結合図の同等のステートメントであることを示すことができます。
f <=< unit == f
unit <=< f == f
f <=< (g <=< h) == (f <=< g) <=< h
ダイアグラム表現に興味がある場合は、文字列ダイアグラムで表現する方法について少し書いています。