Un foo gratuit se trouve être la chose la plus simple qui satisfait toutes les lois du foo. C'est-à-dire qu'il satisfait exactement aux lois nécessaires pour être un fou et rien de plus.
Un foncteur oublieux est celui qui «oublie» une partie de la structure en passant d'une catégorie à l'autre.
Des foncteurs donnés F : D -> C
, et G : C -> D
, disons-nous F -| G
, F
sont adjoints à gauche G
ou G
sont adjoints à droite F
chaque fois que tout a, b: F a -> b
est isomorphe à a -> G b
, où les flèches proviennent des catégories appropriées.
Formellement, un foncteur libre est laissé adjoint à un foncteur oublieux.
Le monoïde gratuit
Commençons par un exemple plus simple, le monoïde libre.
Prenez un monoïde, qui est défini par un ensemble de support T
, une fonction binaire pour écraser une paire d'éléments ensemble f :: T → T → T
, et unit :: T
, de sorte que vous avez une loi associative, et une loi d'identité: f(unit,x) = x = f(x,unit)
.
Vous pouvez créer un foncteur à U
partir de la catégorie des monoïdes (où les flèches sont des homomorphismes monoïdes, c'est-à-dire qu'ils s'assurent qu'ils correspondent unit
à unit
l'autre monoïde et que vous pouvez composer avant ou après le mappage à l'autre monoïde sans changer de signification) à la catégorie d'ensembles (où les flèches ne sont que des flèches de fonction) qui «oublie» l'opération et unit
, et vous donne simplement l'ensemble de support.
Ensuite, vous pouvez définir un foncteur F
de la catégorie des ensembles à la catégorie des monoïdes qui reste adjointe à ce foncteur. Ce foncteur est le foncteur qui associe un ensemble a
au monoïde [a]
, où unit = []
et mappend = (++)
.
Donc, pour passer en revue notre exemple jusqu'à présent, en pseudo-Haskell:
U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a
F : Set → Mon -- is our free functor
F a = ([a],(++),[])
Ensuite, pour montrer que F
c'est gratuit, nous devons démontrer qu'il est laissé adjoint à U
, un foncteur oublieux, c'est-à-dire, comme nous l'avons mentionné ci-dessus, nous devons montrer que
F a → b
est isomorphe à a → U b
maintenant, rappelez-vous que la cible de F
est dans la catégorie Mon
des monoïdes, où les flèches sont des homomorphismes monoïdes, nous avons donc besoin d'un pour montrer qu'un homomorphisme monoïde de [a] → b
peut être décrit précisément par une fonction de a → b
.
Dans Haskell, nous appelons le côté de cela qui vit dans Set
(euh, Hask
la catégorie de types Haskell que nous prétendons être Set), juste foldMap
, qui, lorsqu'elle est spécialisée de Data.Foldable
à Lists, a du type Monoid m => (a → m) → [a] → m
.
Il y a des conséquences qui découlent de cette adjonction. Notamment, si vous oubliez, puis construisez avec free, puis oubliez à nouveau, c'est comme vous l'avez oublié une fois, et nous pouvons l'utiliser pour construire la jointure monadique. depuis UFUF
~ U(FUF)
~ UF
, et nous pouvons passer dans l'homomorphisme monoïde d'identité de [a]
à [a]
travers l'isomorphisme qui définit notre adjonction, obtenir qu'un isomorphisme de liste [a] → [a]
est une fonction de type a -> [a]
, et c'est juste un retour pour les listes.
Vous pouvez composer tout cela plus directement en décrivant une liste en ces termes avec:
newtype List a = List (forall b. Monoid b => (a -> b) -> b)
La monade libre
Qu'est-ce qu'une Free Monad ?
Eh bien, nous faisons la même chose que nous faisions avant, nous commençons avec un foncteur oublieux U de la catégorie des monades où les flèches sont des homomorphismes de monade à une catégorie d'endofoncteurs où les flèches sont des transformations naturelles, et nous recherchons un foncteur qui est laissé adjoint pour que.
Alors, comment cela se rapporte-t-il à la notion de monade libre telle qu'elle est généralement utilisée?
Savoir que quelque chose est une monade libre, Free f
vous dit que donner un homomorphisme de monade à partir de Free f -> m
, c'est la même chose (isomorphe à) que donner une transformation naturelle (un homomorphisme de foncteur) à partir de f -> m
. Rappelez-vous que F a -> b
doit être isomorphe pour a -> U b
que F soit laissé adjoint à U. U ici mappé des monades aux foncteurs.
F est au moins isomorphe au Free
type que j'utilise dans mon free
package sur le piratage.
Nous pourrions également le construire dans une analogie plus étroite avec le code ci-dessus pour la liste gratuite, en définissant
class Algebra f x where
phi :: f x -> x
newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)
Cofree Comonads
Nous pouvons construire quelque chose de similaire, en regardant l'adjoint de droite d'un foncteur oublieux en supposant qu'il existe. Un foncteur cofree est simplement / à droite adjoint / à un foncteur oublieux, et par symétrie, savoir que quelque chose est un comonad cofree revient à savoir que donner un homomorphisme comonad à partir de w -> Cofree f
est la même chose que donner une transformation naturelle à partir de w -> f
.