77 votes

Monades comme adjonctions

J'ai lu des articles sur les monades dans la théorie des catégories. Une définition des monades utilise une paire de foncteurs adjoints. Une monade est définie par un aller-retour utilisant ces foncteurs. Apparemment, les adjonctions sont très importantes dans la théorie des catégories, mais je n'ai vu aucune explication des monades de Haskell en termes de foncteurs adjoints. Quelqu'un a-t-il pensé à cela?

39voto

sclv Points 25335

Edit: Juste pour le fun, je vais faire de ce droit. Réponse originale à cette question conservé ci-dessous

Le courant de contiguïté code de catégorie-les extras est maintenant dans le adjunctions paquet: http://hackage.haskell.org/package/adjunctions

Je vais juste travailler par le biais de l'état monade explicitement et simplement. Ce code utilise Data.Functor.Compose des transformateurs du package, mais sinon autonome.

Une contiguïté entre f (D -> C) et g (C -> D), écrit-f| g, peut être caractérisé par un certain nombre de façons. Nous allons utiliser le counit/unité (epsilon/eta) description, ce qui donne deux les transformations naturelles (morphisms entre foncteurs).

class (Functor f, Functor g) => Adjoint f g where
     counit :: f (g a) -> a
     unit   :: a -> g (f a)

Notez que le "a" dans counit est vraiment l'identité foncteur de C, et la "une" de l'unité est vraiment l'identité foncteur en D.

Nous pouvons également récupérer les hom-jeu de contiguïté définition de la counit/définition de l'unité.

phiLeft :: Adjoint f g => (f a -> b) -> (a -> g b)
phiLeft f = fmap f . unit

phiRight :: Adjoint f g => (a -> g b) -> (f a -> b)
phiRight f = counit . fmap f

Dans tous les cas, nous pouvons maintenant définir une Monade de notre unité/counit contiguïté comme suit:

instance Adjoint f g => Monad (Compose g f) where
    return x = Compose $ unit x
    x >>= f  = Compose . fmap counit . getCompose $ fmap (getCompose . f) x

Maintenant, nous pouvons mettre en œuvre le classique de contiguïté entre (a) et (a ->):

instance Adjoint ((,) a) ((->) a) where
    -- counit :: (a,a -> b) -> b
    counit (x, f) = f x
    -- unit :: b -> (a -> (a,b))
    unit x = \y -> (y, x)

Et maintenant, un type synonyme

type State s = Compose ((->) s) ((,) s)

Et si nous charger de cette opération dans ghci, nous pouvons confirmer que l'État est précisément notre classique de l'état de monade. Notez que nous pouvons prendre à l'opposé de la composition et obtenir le Costate Comonad (aka le magasin comonad).

Il y a un tas d'autres adjunctions nous pouvons faire dans les monades dans ce mode (comme (Bool) Paire), mais ils sont une sorte d'étrange monades. Malheureusement nous ne pouvons pas faire la adjunctions qui induisent le Lecteur et l'Écrivain directement en Haskell d'une manière agréable. Nous pouvons faire de Suite, mais comme copumpkin décrit, qui nécessite une contiguïté à partir d'une face de la catégorie, de sorte qu'il utilise en fait une autre "forme" de la "Adjoint" typeclass qui renverse quelques flèches. Ce formulaire est également mis en œuvre dans un autre module dans le adjunctions paquet.

ce matériau est recouvert d'une manière différente par Derek Elkins article dans La Monade Lecteur 13 -- Calcul des Monades avec la Catégorie de la Théorie: http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf

Aussi, Hinze récentes Extensions de Kan pour l'Optimisation du Programme de papier promenades à travers la construction de la liste monade de la contiguïté entre Mon et Set: http://www.cs.ox.ac.uk/ralf.hinze/Kan.pdf


Vieille réponse:

Deux références.

1) la Catégorie extras offre, comme toujours, avec une représentation de adjunctions et comment les monades en découlent. Comme d'habitude, il est bon de penser, mais jolie lumière sur la documentation: http://hackage.haskell.org/packages/archive/category-extras/0.53.5/doc/html/Control-Functor-Adjunction.html

2) -Café offre également prometteurs, mais une brève discussion sur le rôle de la contiguïté. Qui peut l'aider dans l'interprétation de catégorie-les extras: http://www.haskell.org/pipermail/haskell-cafe/2007-December/036328.html

10voto

copumpkin Points 1894

Derek Elkins me montrait récemment au dîner comment la Cont Monad découle de la composition du foncteur contravariant (_ -> k) avec lui-même, puisqu'il se trouve qu'il est auto-adjoint. C'est comme ça que vous obtenez (a -> k) -> k . Son conseil, cependant, mène à l'élimination de la double négation, ce qui ne peut pas être écrit en Haskell.

Pour du code Agda qui illustre et prouve ceci, veuillez consulter http://hpaste.org/68257 .

8voto

takosuke Points 61

C'est un vieux thread, mais je trouve la question intéressante, j'ai donc fait quelques calculs moi-même. Espérons que Bartosz est toujours là et peut lire ceci..

En fait, la Eilenberg-Moore construction donne une image très claire dans ce cas. (Je vais utiliser CWM notation avec Haskell comme syntaxe)

Laissez - T la liste monade < T,eta,mu > (eta = return et mu = concat) et d'envisager un T-algèbre h:T a -> a.

(À noter qu' T a = [a] gratuite est un monoïde <[a],[],(++)>, qui est, de l'identité [] et la multiplication (++).)

Par définition, h doit satisfaire h.T h == h.mu a et h.eta a== id.

Maintenant, certains facile diagramme de chasser prouve qu' h fait induit une structure de monoïde sur un (défini par l' x*y = h[x,y] ), et qu' h devient un monoïde homomorphism pour cette structure.

A l'inverse, toute structure de monoïde < a,a0,* > défini dans Haskell est naturellement défini comme un T-algèbre.

De cette façon (h = foldr ( * ) a0, une fonction qui "remplace" (:) avec (*),et les cartes, [] de a0, l'identité).

Donc, dans ce cas, la catégorie de T-algèbres est juste la catégorie de monoïde des structures définissable en Haskell, HaskMon.

(Veuillez vérifier que le morphisms T-algèbres sont en fait monoïde homomorphisms.)

Elle caractérise également les listes universel objets dans HaskMon, tout comme des produits gratuits en Grp, polynôme anneaux en CRng, etc.

Le adjuction correspondant à la construction précédente est - < F,G,eta,epsilon >

  • F:Hask -> HaskMon, ce qui prend un type un pour le " libre-monoïde généré par a',c'est - [a],
  • G:HaskMon -> Hask, les oublieux foncteur (oublier la multiplication),
  • eta:1 -> GF , la transformation naturelle définie par \x::a -> [x],
  • epsilon: FG -> 1 , la transformation naturelle définie par la fonction de pliage ci-dessus (le "surjection canonique" à partir d'un monoïde libre à son monoïde quotient)

Ensuite, il y a une autre catégorie de Kleisli' et de la contiguïté. Vous pouvez vérifier que c'est juste la catégorie de Haskell types avec morphisms a -> T b, où ses compositions sont données par la soi-disant "Kleisli composition' (>=>). Un typique Haskell programmeur trouverez cette catégorie de plus en plus familiers.

Enfin,comme il est illustré dans CWM, la catégorie des T-algèbres (resp. Catégorie de Kleisli) devient le terminal (resp. initiale) de l'objet dans la catégorie de adjuctions qui définissent la liste monade T dans un sens.

Je vous suggère de faire des calculs similaires pour l'arbre binaire foncteur T a = L a | B (T a) (T a) pour vérifier votre compréhension.

2voto

Bartosz Milewski Points 1739

J'ai trouvé un standard constructions de complément foncteurs pour toute monade par Eilenberg-Moore, mais je ne suis pas sûr si elle ajoute aucune idée du problème. La deuxième catégorie dans la construction est une catégorie de T-algèbres. Un T algèbre ajoute un "produit" à la catégorie initiale.

Alors, comment serait-il travailler pour une liste monade? Le foncteur dans la liste monade se compose d'un constructeur de type, par exemple, Int->[Int] et une cartographie des fonctions (par exemple, la norme d'application de la carte à des listes). Une algèbre ajoute une cartographie à partir des listes d'éléments. Un exemple serait d'ajouter (ou de se multiplier) tous les éléments d'une liste d'entiers. Le foncteur F prend n'importe quel type, par exemple, de type Int, et les cartes dans l'algèbre définie sur les listes de type Int, où le produit est défini par monadique de joindre (ou vice-versa, la jointure est défini comme le produit). L'oublieux foncteur G prend une algèbre et oublie le produit. La paire F, G, adjoint de foncteurs est ensuite utilisée pour construire la monade de la manière habituelle.

Je dois dire que je suis pas plus avancé.

1voto

tokosuke Points 11

Si vous êtes intéressé,voici quelques réflexions d'un non-expert sur le rôle des monades et adjunctions dans les langages de programmation:

Tout d'abord, il existe pour une monade T unique contiguïté pour la catégorie de Kleisli T. En Haskell,l'utilisation de monades se limite principalement à des opérations dans cette catégorie (qui est essentiellement une catégorie de libre-algèbres,pas de quotients). En fait, tout ce qu'on peut faire avec un Haskell Monade est de composer la Kleisli morphisms de type a->T b grâce à l'utilisation d'expressions, (>>=), etc., pour créer un nouveau morphism. Dans ce contexte, le rôle des monades est restreinte à l'économie de notation.On exploite l'associativité de l'morphisms pour être en mesure d'écrire (dire) [0,1,2] au lieu de (Cons 0 (Cons 1 (Cons 2 Nil))), qui est, vous pouvez écrire séquence de séquence de, pas comme un arbre.

Même l'utilisation de IO monades est non essentiel, pour le courant Haskell type de système est puissant suffisant pour réaliser l'encapsulation de données (existentielle).

C'est ma réponse à votre question de départ, mais je suis curieux de ce que Haskell experts ont à dire à ce sujet.

D'autre part, comme nous l'avons noté, il y a aussi une correspondance 1-1 entre les monades et adjunctions (T)algèbres. Adjoints, dans MacLane, sont " une façon pour exprimer les équivalences de catégories.' Dans un décor typique de adjunctions <F,G>:X->AF est une sorte de "libre-algèbre génératrice' et G 'oublieux foncteur", le correspondant de la monade sera (grâce à l'utilisation de T-algèbres) décrire comment (et quand) la structure algébrique de l' A est construit sur les objets de l' X.

Dans le cas de Hask et la liste monade T, la structure qui T introduit, c'est que de monoïde,et cela peut nous aider à établir les propriétés (y compris l'exactitude du code algébriques méthodes de la théorie de la monoids fournit. Par exemple, la fonction foldr (*) e::[a]->a peut facilement être vu comme un cadre associatif fonctionnement tant qu' <a,(*),e> est un monoïde, un fait qui pourrait être exploité par le compilateur d'optimiser le calcul (par exemple, par parallélisme). Une autre application consiste à identifier et classer les 'récursivité des schémas de programmation fonctionnelle en utilisant catégorique méthodes dans l'espoir de (partiellement) élimination du "goto de la programmation fonctionnelle', Y (l'arbitraire de la récursivité combinator).

Apparemment, ce genre d'application est l'une des principales motivations des créateurs de la Théorie de la Catégorie (MacLane, Eilenberg, etc.), à savoir, pour établir naturel équivalence de catégories, et le transfert d'une méthode bien connue dans une catégorie à l'autre (par exemple homologique méthodes d'espaces topologiques,des méthodes algébriques pour la programmation, etc.). Ici, les adjoints et les monades sont des outils indispensables pour exploiter cette connexion de catégories. (D'ailleurs, la notion de monades (et son double, comonads) est si générale que l'on peut même aller jusqu'à définir "cohomologies' de Haskell types.Mais je n'ai pas une pensée encore).

Comme pour les non-determistic fonctions que vous avez mentionné, j'ai beaucoup moins de choses à dire... Mais notez que, si une contiguïté <F,G>:Hask->A pour certaines catégorie A définit la liste monade T, il doit y avoir un unique foncteur de comparaison' K:A->MonHask (catégorie de monoids définissable en Haskell), voir CWM. Cela signifie, en effet, que votre catégorie d'intérêt doit être une catégorie de monoids dans certaines forme restreinte (par exemple, il peut manquer certains quotients, mais pas gratuitement algèbres) afin de définir la liste monade.

Enfin,quelques remarques:

L'arbre binaire foncteur je l'ai mentionné dans mon dernier message généralise facilement à l'arbitraire de type de données T a1 .. an = T1 T11 .. T1m | .... À savoir,tout type de données en Haskell définit naturellement une monade (avec les correspondants de la catégorie des algèbres et la catégorie de Kleisli), qui n'est que le résultat de toutes les données constructeur en Haskell être total. C'est une autre raison pourquoi je considère que Haskell Monade classe n'est pas beaucoup plus qu'une syntaxe de sucre (ce qui est assez important dans la pratique,bien sûr).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X