Sur une réponse précédente Petr Pudlak a défini le CFunctor
pour les foncteurs autres que ceux de la classe Hask a Hask . En le réécrivant un peu à l'aide de familles de types, on obtient les résultats suivants
class CFunctor f where
type Dom f :: * -> * -> * -- domain category
type Cod f :: * -> * -> * -- codomain category
cmap :: Dom f a b -> Cod f (f a) (f b) -- map morphisms across categories
avec des instances qui ressemblent par exemple à
instance CFunctor Maybe where
type Dom Maybe = (->) -- domain is Hask
type Cod Maybe = (->) -- codomain is also Hask
cmap f = \m -> case m of
Nothing -> Nothing
Just x -> Just (f x)
Dans la théorie des catégories, chaque fois que F : C --> D est un foncteur et G : D --> E est un foncteur, alors la composition GF : C --> E est également un foncteur.
J'aimerais exprimer cela en Haskell. Comme je ne peux pas écrire instance CFunctor (f . g)
J'introduis une classe d'enveloppe :
newtype Wrap g f a = Wrap { unWrap :: g (f a) }
En écrivant le CFunctor
Si j'arrive jusqu'à
instance (CFunctor f, CFunctor g, Cod f ~ Dom g) => CFunctor (Wrap g f) where
type Dom (Wrap g f) = Dom f
type Cod (Wrap g f) = Cod g
cmap = undefined
mais je n'arrive pas à comprendre ce que l'implémentation de la cmap
devrait être. Des conseils ?
PS la raison éventuelle de tout ceci est d'introduire aussi une classe Adjunction
avec des méthodes unit
y counit
puis de dériver automatiquement des instances de monades à partir d'adjonctions. Mais d'abord, je dois montrer au compilateur que la composition de deux foncteurs est aussi un foncteur.
Je suis conscient que je pourrais utiliser cmap.cmap
sur un objet de type g (f a)
et cela fonctionnerait, mais cela ressemble un peu à de la triche - un foncteur est sûrement juste un foncteur, et le compilateur ne devrait pas avoir à savoir qu'il est en fait la composition de deux autres foncteurs ?