Les applicatifs composent, les monades non.
Que signifie la déclaration ci-dessus? Et quand l'un est-il préférable à l'autre?
Les applicatifs composent, les monades non.
Que signifie la déclaration ci-dessus? Et quand l'un est-il préférable à l'autre?
Applicative
s sont en fait une famille entière deMonad
s, à savoir un pour chaque "forme" de structure possible.ZipList
n'est pas aMonad
, mais lesZipList
s d'une longueur fixe le sont.Reader
est un cas spécial pratique (ou est-ce général?) où la taille de la "structure" est fixée comme cardinalité du type d'environnement.Reader
monade jusqu'à l'isomorphisme. Une fois que vous avez fixé la forme d'un conteneur, il encode efficacement une fonction à partir de positions, comme un mémo trie. Peter Hancock appelle ces foncteurs "Naperian", car ils obéissent aux lois des logarithmes.Réponses:
Si nous comparons les types
nous avons une idée de ce qui sépare les deux concepts. Cela
(s -> m t)
dans le type de(>>=)
montre qu'une valeur danss
peut déterminer le comportement d'un calcul dansm t
. Les monades permettent des interférences entre la valeur et les couches de calcul. L'(<*>)
opérateur n'autorise pas de telles interférences: les calculs de fonction et d'argument ne dépendent pas de valeurs. Cela mord vraiment. Comparerqui utilise le résultat d'un certain effet pour décider entre deux calculs (par exemple le lancement de missiles et la signature d'un armistice), alors que
qui utilise la valeur de
ab
pour choisir entre les valeurs de deux calculsat
etaf
, après avoir effectué les deux, peut-être à un effet tragique.La version monadique repose essentiellement sur la puissance supplémentaire de
(>>=)
choisir un calcul à partir d'une valeur, et cela peut être important. Cependant, soutenir ce pouvoir rend les monades difficiles à composer. Si nous essayons de construire une double liaisonnous arrivons jusqu'ici, mais maintenant nos couches sont toutes mélangées. Nous avons un
n (m (n t))
, donc nous devons nous débarrasser de l'extérieurn
. Comme le dit Alexandre C, nous pouvons le faire si nous avons unpermuter l'
n
intérieur etjoin
lui à l'autren
.La `` double application '' plus faible est beaucoup plus facile à définir
car il n'y a pas d'interférence entre les couches.
En conséquence, il est bon de reconnaître quand vous avez vraiment besoin de la puissance supplémentaire de
Monad
s et quand vous pouvez vous en sortir avec la structure de calcul rigide quiApplicative
prend en charge.Notez, en passant, que bien que composer des monades soit difficile, cela peut être plus que ce dont vous avez besoin. Le type
m (n v)
indique le calcul avecm
-effects, puis le calcul avecn
-effects à unev
-value, où lesm
-effects se terminent avant len
début des -effects (d'où la nécessité deswap
). Si vous voulez juste entrelacerm
-effets avecn
-effects, alors la composition est peut-être trop demander!la source
m
et quen
vous pouvez toujours écrire un transformateur de monademt
et fonctionner enn (m t)
utilisantmt n t
? Donc on peut toujours composer des monades, c'est juste plus compliqué, en utilisant des transformateurs?data Free f x = Ret x | Do (f (Free f x))
, alorsdata (:+:) f g x = Inl (f x) | Tnr (g x)
, et réfléchissezFree (m :+: n)
. Cela retarde le choix de la manière d'exécuter les entrelacements.Maybe
cela signifie qu'un débutNothing
supprimera l'évaluation dua
plus tard / suivantJust a
. Est-ce correct?Monades font Compose, mais le résultat peut - être pas une monade. En revanche, la composition de deux applicatifs est forcément un applicatif. Je soupçonne que l'intention de la déclaration originale était que «l'applicitation compose, tandis que la monadisme ne le fait pas». Reformulé, «
Applicative
est fermé sous la composition, etMonad
n'est pas».la source
Si vous avez des applicatifs
A1
etA2
, alors le typedata A3 a = A3 (A1 (A2 a))
est également applicatif (vous pouvez écrire une telle instance de manière générique).Par contre, si vous avez des monades
M1
et queM2
le typedata M3 a = M3 (M1 (M2 a))
n'est pas forcément une monade (il n'y a pas d'implémentation générique sensée pour>>=
oujoin
pour la composition).Un exemple peut être le type
[Int -> a]
(ici nous composons un constructeur de type[]
avec(->) Int
, qui sont tous deux des monades). Vous pouvez facilement écrireEt cela se généralise à tout applicatif:
Mais il n'y a pas de définition sensée de
Si vous n'êtes pas convaincu de cela, considérez cette expression:
La longueur de la liste retournée doit être définie dans la pierre avant qu'un entier ne soit fourni, mais la longueur correcte de celle-ci dépend de l'entier fourni. Ainsi, aucune
join
fonction correcte ne peut exister pour ce type.la source
IO
sans unMonad
serait très difficile à programmer. :)Composer des monades, http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
la source
swap : N M a -> M N a
ContT r m a
n'est nim (Cont r a)
niCont r (m a)
, etStateT s m a
est approximativementReader s (m (Writer s a))
.swap
implique que la composition laisse les deux "coopérer" d'une manière ou d'une autre. Notez également qu'ilsequence
s'agit d'un cas particulier de "swap" pour certaines monades. Ainsi estflip
, en fait.swap :: N (M x) -> M (N x)
il me semble que vous pouvez utiliserreturns
(convenablementfmap
ped) pour insérer unM
à l'avant et unN
à l'arrière, en partant deN (M x) -> M (N (M (N x)))
, puis utiliser lejoin
du composite pour obtenir votreM (N x)
.La solution de loi distributive l: MN -> NM suffit
pour garantir la monadicité de NM. Pour voir cela, vous avez besoin d'une unité et d'un mult. Je vais me concentrer sur le mult (l'unité est unit_N unitM)
Cela ne garantit pas que MN est une monade.
L'observation cruciale entre cependant en jeu lorsque vous avez des solutions de droit de la distribution
ainsi, LM, LN et MN sont des monades. La question se pose de savoir si LMN est une monade (soit par
(MN) L -> L (MN) ou par N (LM) -> (LM) N
Nous avons suffisamment de structure pour créer ces cartes. Cependant, comme l' observe Eugenia Cheng , nous avons besoin d'une condition hexagonale (qui équivaut à une présentation de l'équation de Yang-Baxter) pour garantir la monadicité de l'une ou l'autre construction. En fait, avec la condition hexagonale, les deux monades différentes coïncident.
la source