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 Applicative
comme "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 Applicative
avec 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 Applicative
que 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 Monad
est sans doute un artefact des limitations implicites à Applicative
faire 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:CCo p C→ DCo p→ Do pHa s ko pApplicative
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' Applicative
existence. 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 .Ha s ko pnewtype Op b a = Op (a -> b)
Ha s kb → aHa s ko pOp b a
Ha s k
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:Ha s kApplicative
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)
à copure
produirait une comonade (en supposant que les lois soient satisfaites), bien sûr. Mais il n'y a pas de relation évidente entre - coap
quoi 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 cozip
peu 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.Ha s ko pb <~ a
contracurry :: (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.Ha s kCoApplicative
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.