Existe-t-il un concept de quelque chose comme des foncteurs co-applicatifs assis entre les comonades et les foncteurs?

17

Toute monade est également un foncteur applicatif et tout foncteur applicatif est un foncteur. De plus, tout comonad est un foncteur. Existe-t-il un concept similaire entre les comonades et les foncteurs, quelque chose comme le foncteur co-applicatif, et quelles sont ses propriétés?

FoncteursFoncteursFoncteurs applicatifs???MonadesComonads

Mise à jour: je serais également intéressé par les utilisations possibles d'un tel concept.

Petr Pudlák
la source
Êtes-vous sûr que vous ne cherchiez pas Comonads -> ??? -> Cofoncteurs?
josiah
1
@josiah Non, autant que je sache, les comonades sont des foncteurs , pas des cofoncteurs.
Petr Pudlák
1
N'est-ce pas divisible cette pièce manquante?
Gus

Réponses:

15

Tout d'abord:

Toute monade est également un foncteur applicatif et tout foncteur applicatif est un foncteur.

Cela est vrai dans le contexte de Haskell, mais (à lire Applicativecomme "foncteur monoïdal fort laxiste") pas en général, pour la raison plutôt banale que vous pouvez avoir des foncteurs "applicatifs" entre différentes catégories monoïdales, alors que les monades (et les comonades) sont des endofuncteurs .

De plus, l'identification Applicativeavec des foncteurs monoïdaux laxistes forts est légèrement trompeuse, car pour justifier le nom (et la signature de type de (<*>)), il faut un foncteur entre les catégories monoïdales fermées qui préserve à la fois la structure monoïdale et le hom interne . On pourrait vraisemblablement appeler cela un "foncteur monoïdal fermé laxiste", sauf qu'un foncteur entre catégories fermées monoïdales qui préserve l'une ou l'autre propriété préserve l'autre de façon évidente . Parce Applicativeque ne décrit que les endofoncteurs sur Hask préservant la structure monoïdale de (,), ses instances acquièrent automatiquement de nombreuses propriétés, y compris leur résistance , qui peuvent ainsi être élidées.

Le lien apparent avec Monadest sans doute un artefact des limitations implicites à Applicativefaire coïncider des aspects de leurs structures monoïdes respectives, une heureuse coïncidence qui, malheureusement, ne survit pas à la dualisation.

Tout comme une comonade sur une catégorie est une monade sur , un foncteur monoïde oplax est un foncteur monoïde laxiste . Mais n'est pas monoïdal fermé , et un co- qui n'inclut pas d'application de fonction mérite à peine le nom. De toute façon, le résultat ne serait pas terriblement intéressant:CCop CCopopHuneskopApplicative

class (Functor f) => CoMonoidal f where
    counit :: f () -> ()
    cozip :: f (a, b) -> (f a, f b)

On pourrait plutôt imaginer une notion de "colax fermé fonctor", qui ressemblerait beaucoup plus à l' Applicativeexistence. Malheureusement, n'est pas (à ma connaissance) une catégorie fermée du tout: dans correspond aux morphismes dans , mais ne fonctionne pas comme un hom interne là-bas - parce que les flèches sont inversées, une sorte de co-fonction serait nécessaire à la place, que nous ne pouvons pas définir en général pour .Huneskopnewtype Op b a = Op (a -> b)HuneskbuneHuneskopOp b aHunesk

Si nous prétendons simplement que des "foncteurs fermés colax" existent pour , et que nous travaillons en outre de la manière que nous espérions naïvement, un co- basé sur cela ressemblerait probablement à ceci:HuneskApplicative

class (Functor f) => CoApplicative f where
    copure :: f a -> a
    coap :: (f a -> f b) -> f (a -> b)

Ajouter duplicate :: f a -> f (f a)à copureproduirait une comonade (en supposant que les lois soient satisfaites), bien sûr. Mais il n'y a pas de relation évidente entre - coapquoi que ce soit - et extend :: (f a -> b) -> f a -> f b. En comparant les types, il devient clair que la dualisation se produit de différentes manières: les structures comonoïdales sous duplicate- jacentes et cozippeu liées les unes aux autres ou avec coap(ce qui n'a probablement aucun sens de toute façon), tandis que liftA2 (,)et (<*>)sont équivalentes et peuvent être dérivées de join.

Une autre façon possible de dualiser Applicative, qui a encore moins à voir avec les comonades, est de considérer les foncteurs monoïdes contravariants:

class (Contravariant f) => ContraMonoidal f where
    contraunit :: f a
    contrazip :: f a -> f b -> f (Either a b)

Mais cela va à l'encontre des mêmes problèmes que ci-dessus, à savoir que n'est pas une catégorie fermée. Si elle était, nous aurions un certain type de telle sorte que nous pourrions écrire des fonctions comme et et ainsi de suite qui fonctionnait vraiment comme prévu.Huneskopb <~ acontracurry :: (Either c b <~ a) -> (c <~ (b <~ a))contraapply :: b -> Either a (a <~ b)

Si ma mémoire est bonne, les obstacles ici ne sont pas spécifiques à Haskell, mais découlent plutôt du fait que est fermé cartésien (jusqu'à l'ondulation habituelle, bien sûr), une propriété qu'il partage avec la plupart des calculs lambda typés, donc vous n'êtes pas susceptible d'aller très loin avec un dans la plupart des paramètres.HuneskCoApplicative

Cependant, dans une catégorie fermée monoïdale plus hospitalière à la dualisation, vous pourriez avoir plus de chance. En particulier, je crois que les deux Kleisli (Cont r)et sa catégorie opposée sont monoïdales fermées, ce qui pourrait être un meilleur contexte pour explorer ces idées.

CA McCann
la source
En comparant votre réponse à cstheory.stackexchange.com/a/22302/989 , il est surprenant que vous ne dualisiez pas les produits en sommes. Bien sûr, vous avez raison de dire que Hask n'a pas de sommes catégoriques; mais si vous êtes prêt à vous limiter à la catégorie des programmes totaux (comme dans Agda), supposons que c'est réglé pour l'instant, ce problème disparaît. (Je ne dis pas que Set ^ op est monoïdal fermé, mais je soupçonne que ce que je dis implique).
Blaisorblade
8

Dans cet article sur SO, j'ai trouvé une réponse intéressante - des foncteurs décisifs . Si nous remplaçons ()par Void, (,)par Either et inversons les flèches, nous obtenons:

class Functor f => Decisive f where
    nogood :: f Void -> Void
    orwell :: f (Either s t) -> Either (f s) (f t)

Le billet de blog donne également quelques lois auxquelles adhèrent les foncteurs décisifs.

Et, tout Comonadest aussi Decisive:

instance Comonad c => Decisive c where
    nogood = counit
    orwell story = case counit story of
                     Left s  -> fmap (either id (const s)) story
                     Right t -> fmap (either (const t) id) story 

Les foncteurs décisifs se situent donc entre les foncteurs et les comonades, tout comme les foncteurs applicatifs se situent entre les foncteurs et les monades.

Petr Pudlák
la source
6

McBride et Patterson (section 7) montrent qu'un foncteur applicatif, également connu sous le nom d'idiome, est un foncteur monoïde fort laxiste . Vous êtes à la recherche d'un puissant foncteur monoïde colax également connu sous le nom de foncteur monoïde oplax fort . Comme mentionné dans un commentaire, un foncteur monoïde oplax est un foncteur monoïde laxiste entre les catégories opposées, ce qui finit par être une version comonoïdale d'un foncteur monoïde laxiste.

Dessinez les diagrammes, inversez les flèches!

Je devrais passer un peu de temps à travailler sur les détails pour voir de quoi il s'agit et à le traduire en une notion de programmation fonctionnelle.

Dave Clarke
la source
Pour une raison quelconque, le terme standard semble être "foncteur monoïde oplax". L'idée est un foncteur monoïde laxiste entre les catégories opposées, qui finit par être une version comonoïdale d'un foncteur monoïde laxiste. L'utilisation de «colax comonoidal» est soit redondante, soit équivalente à «lax monoidal».
CA McCann
J'ai exagéré le "co" -ing. Je vais corriger ma réponse.
Dave Clarke