Grosso modo, Haskell ne sa catégorie théorie dans une seule catégorie dont les objets sont Haskell types et dont les flèches sont des fonctions entre ces types. Ce n'est certainement pas un usage général de la langue pour la modélisation de la catégorie de la théorie.
Un (mathématiques) foncteur est une opération de tourner les choses dans une catégorie dans des choses d'une autre, éventuellement totalement différent, de la catégorie. Un endofunctor est alors un foncteur qui arrive à avoir la même source et cible les catégories. En Haskell, un foncteur est une opération de tourner les choses dans la catégorie des Haskell types dans d'autres choses aussi dans la catégorie de Haskell types, de sorte qu'il est toujours un endofunctor.
[Si vous êtes à la suite de la littérature mathématique, techniquement, l'opération "(a->b)->(m a -> m b) "n'est que la flèche de la partie de la endofunctor m, et" m " est la partie de l'objet]
Lorsque Haskellers parler de travailler dans une "monade", ils signifient vraiment de travail dans la catégorie de Kleisli de la monade. La catégorie de Kleisli une monade est un fond de confusion bête au premier abord, et normalement besoin d'au moins deux couleurs d'encre pour donner une bonne explication, afin de prendre la tentative suivante pour ce qu'il est et découvrez quelques références (malheureusement, Wikipédia est inutile ici pour tous, mais le droit définitions).
Supposons que vous avez une monade " m " sur la catégorie C de la Haskell types. Sa catégorie de Kleisli Kl(m) a les mêmes objets que C, à savoir Haskell types, mais une flèche un ~(f)~> b dans Kl(m) est une flèche de a -(f)-> mo C. (j'ai utilisé une ligne sinueuse dans mon Kleisli flèche pour distinguer les deux). Je le répète: les objets et les flèches de la Kl(C) sont aussi des objets et des flèches de C, mais les flèches pointent vers différents objets de Kl(C) que dans C. Si ce n'est pas vous frapper aussi étrange, le relire plus attentivement!
Concrètement, Peut-être envisager la monade. Sa catégorie de Kleisli est juste la collection de Haskell types, et ses flèches un ~(f)~> b sont des fonctions de a -(f)-> Peut-être que b. Ou de considérer l' (État s) monade dont les flèches sont un ~(f)~> b sont des fonctions de a -(f)-> (État s b) == a(f)-> (s->(s,b)). Dans tous les cas, vous êtes toujours à écrire un enchevêtrées flèche, comme un raccourci pour faire quelque chose pour le type de l'arrivée de vos fonctions.
[Notez que l'État n'est pas une monade, parce que l'État est * -> * -> *, de sorte que vous devez fournir l'un des paramètres de type de la transformer en mathématiques monade.]
C'est très bien, je l'espère, mais supposons que vous souhaitez composer des flèches un ~(f)~> b et b ~(g)~> c. Ce sont vraiment des Haskell fonctions a -(f)-> mo et b -(g)-> mc que vous ne pouvez pas composer parce que les types ne correspondent pas. La solution mathématique est d'utiliser la "multiplication" transformation naturelle u:mm->m de la monade comme suit: a ~f)~> b ~(g)~> c == a -(f)-> mo -(mg)-> mmc(u_c)-> mc pour obtenir une flèche a->mc qui est un Kleisli flèche d'un ~(f;g)~> c tel que requis.
Peut-être un exemple concret permet ici. Dans la monade Peut-être, vous ne pouvez pas composer des fonctions f : a -> Peut-être b et g : b -> Peut-être que c directement, mais en soulevant g de
Maybe_g :: Maybe b -> Maybe (Maybe c)
Maybe_g Nothing = Nothing
Maybe_g (Just a) = Just (g a)
et à l'aide de la "évidentes"
u :: Maybe (Maybe c) -> Maybe c
u Nothing = Nothing
u (Just Nothing) = Nothing
u (Just (Just c)) = Just c
vous pouvez former la composition u . Maybe_g . f
ce qui est la fonction a -> Peut-être que c que tu voulais.
Dans l' (État s) monade, c'est similaire, mais messier: étant Donnés deux monadique des fonctions d'une ~(f)~> b et b ~(g)~> c qui sont vraiment un -(f)-> (s->(s,b)) et b -(g)-> (s->(s,c)) sous le capot, vous les composer en soulevant g en
State_s_g :: (s->(s,b)) -> (s->(s,(s->(s,c))))
State_s_g p s1 = let (s2, b) = p s1 in (s2, g b)
ensuite, vous appliquez la "multiplication" la transformation naturelle de u, qui est
u :: (s->(s,(s->(s,c)))) -> (s->(s,c))
u p1 s1 = let (s2, p2) = p1 s1 in p2 s2
qui (un peu) les bougies de l'état final de l' f
dans l'état initial de l' g
.
En Haskell, cela s'avère être un peu de façon naturelle à travailler si au lieu de cela, il y a la (>>=)
fonction qui fait la même chose que u, mais d'une manière qui rend plus facile à implémenter et à utiliser. Ceci est important: (>>=)
n'est pas la transformation naturelle de 'u'. Vous pouvez définir chacun des termes de l'autre, de sorte qu'ils sont équivalents, mais ils ne sont pas la même chose. Le Haskell version de " u " est écrit join
.
L'autre chose qui manque à cette définition de Kleisli catégories est l'identité sur chaque objet: a ~(1_a)~> un qui est vraiment un -(n_a)-> ma, où n est le 'unité de transformation naturelle. C'est écrit return
en Haskell, et ne semble pas causer beaucoup de confusion.
J'ai appris catégorie de théorie avant que j'arrive à Haskell, et j'ai aussi eu de la difficulté avec le décalage entre ce que les mathématiciens appellent une monade et à quoi ils ressemblent en Haskell. C'est pas plus facile dans l'autre sens!