37

圏論では、モナドは2つの随伴関手から構築できます。特に、CDがカテゴリで、 F:C-> DG:D-> Cが随伴関手である場合、全単射があるという意味で

hom(FX、Y)= hom(X、GY)

CXDのYごとに、合成G o F:C->Cはモナドです。


随伴関手のそのようなペアの1つは、型bを固定し、取るFとなることによって与えることができGます

data F b a = F (a,b)
data G b a = G (b -> a)

instance Functor (F b) where
  fmap f (F (a,b)) = F (f a, b)

instance Functor (G b) where
  fmap f (G g) = G (f . g)

そして、hom-sets間の全単射は、カリー化によって与えられます(モジュロコンストラクター)。

iso1 :: (F b a -> c) -> a -> G b c
iso1 f = \a -> G $ \b -> f (F (a,b))

iso2 :: (a -> G b c) -> F b a -> c
iso2 g = \(F (a,b)) -> let (G g') = g a in g' b

この場合、対応するモナドは

data M b a = M { unM :: b -> (a,b) }

instance Monad (M b) where
    return a    = M (\b -> (a,b))
    (M f) >>= g = M (\r -> let (a,r') = f r in unM (g r') a)

このモナドの名前がどうあるべきかはわかりませんが、上書き可能な情報の一部を運ぶリーダーモナドのようなもののようです(編集:State dbauppはコメントでこれがモナドであると指摘しています。 )。

したがって、Stateモナドは随伴関手とのペアとして「分解」することFができ、次のGように書くことができます。

State = G . F

ここまでは順調ですね。


私は今、他の一般的なモナドを随伴関手のペアに分解する方法を理解しようとしています-たとえば、、、、-Maybeしかし[]、それらReaderを「分解」できる随伴関手のペアが何であるかを理解することはできません。WriterCont

唯一の単純なケースはモナドであるように思われます。これは、ファンクターのIdentity任意のペアに分解でき、逆になります(特に、とをとることができます)。FGFGF = IdentityG = Identity

誰かが光を当てることができますか?

4

3 に答える 3

18

あなたが探しているのはクライスリ圏です。もともとは、すべてのモナドが2つの随伴関手から構築できることを示すために開発されました。

問題は、HaskellFunctorが一般的なファンクターではなく、Haskellカテゴリーのエンドファンクターであるということです。したがって、他のカテゴリ間のファンクタを表すには、別の何か(AFAIK)が必要です。

{-# LANGUAGE FunctionalDependencies, KindSignatures #-}
import Control.Arrow
import Control.Category hiding ((.))
import qualified Control.Category as C
import Control.Monad

class (Category c, Category d) => CFunctor f c d | f -> c d where
    cfmap :: c a b -> d (f a) (f b)

->両方cd考慮して、Haskellカテゴリのエンドファンクターを取得した場合、これは次のタイプにすぎないことに注意してくださいfmap

cfmap :: (a -> b) -> (f a -> f b)

cこれで、2つの特定のカテゴリ間のファンクターを表す明示的な型クラスがdでき、特定のモナドの2つの随伴関手を表現できます。左側はオブジェクトaをjustaにマップし、射f(return .) f次のようにマップします。

-- m is phantom, hence the explicit kind is required
newtype LeftAdj (m :: * -> *) a = LeftAdj { unLeftAdj :: a }
instance Monad m => CFunctor (LeftAdj m) (->) (Kleisli m) where
    cfmap f = Kleisli $ liftM LeftAdj . return . f . unLeftAdj
    -- we could also express it as liftM LeftAdj . (return .) f . unLeftAdj

右のものは、オブジェクトaをオブジェクトm aにマップし、射gを、、join . liftM gまたは同等に(=<<) g:にマップします。

newtype RightAdj m a = RightAdj { unRightAdj :: m a }
instance Monad m => CFunctor (RightAdj m) (Kleisli m) (->) where
    cfmap (Kleisli g) = RightAdj . join . liftM g . unRightAdj
    -- this can be shortened as RightAdj . (=<<) g . unRightAdj

(Haskellでこれを表現するより良い方法を誰かが知っているなら、私に知らせてください。)

于 2012-12-18T18:57:12.357 に答える
17
  • Maybe自由関手から先のとがった集合の範疇に入り、忘却関手が戻る
  • []自由関手からモノイドの範疇に入り、忘却関手が元に戻る

しかし、これらのカテゴリはいずれも Hask のサブカテゴリではありません。

于 2012-12-18T20:06:28.130 に答える
8

お気づきのように、随伴関手のすべてのペアはモナドを生成します。逆も成立します。すべてのモナドはそのように発生します。実際、それは 2 つの標準的な方法で行われます。1 つは、Petr が説明する Kleisli の構成です。もう 1 つは Eilenberg-Moore 構成です。実際、Kleisli は初期のそのような方法であり、EM は最終的な方法であり、随伴関手のペアの適切なカテゴリにあります。それらは 1965 年に独立して発見されました。詳細が必要な場合は、Catsters ビデオを強くお勧めします。

于 2013-01-10T11:02:16.470 に答える