Expliqué en 5 minutes : les monades en JavaScript simple
Malgré la photo de couverture intimidante, je vais essayer d'expliquer les monades en utilisant le moins de mathématiques dures possible. Aucune mention de la théorie des catégories, pas de Kleisli, pas même de Curry. Bien qu'il y aura un NaN.
Dans les mots du grand Douglas Crockford :
En plus d'être bon et utile, il est également maudit et la malédiction de la monade est qu'une fois que vous avez l'épiphanie, une fois que vous comprenez - "oh c'est ce que c'est" - vous perdez la capacité de l'expliquer à quelqu'un d'autre.
Eh bien, j'ai une théorie - c'est parce que parmi tous les excellents articles sur ce sujet, qui fournissent une excellente explication de la théorie mathématique derrière les monades, et comment elles devraient être mises en œuvre (avec des exemples exquis !), une chose ne va pas :
Pourquoi en ai-je réellement besoin ?
Avant d'essayer de le savoir, une remarque. Il y a quelque temps, j'ai lu que vous ne devriez vraiment pas essayer de comprendre les monades en vous basant sur quelque chose qui n'est pas fermement basé sur l'explication des mathématiques qui les sous-tendent et sur leur place dans la théorie des catégories. Pour ceux que ça intéresse : il existe d'excellents articles traitant de ce sujet, comme celui-ci , ou celui-ci , ou encore celui qui a introduit les monades dans la programmation à partir de 1992 . Puisque je ne veux vraiment pas les répéter ici, veuillez les lire (ou au moins les scanner) maintenant et revenir ici après (bien que je pense qu'il n'est pas entièrement nécessaire de comprendre ce qui se passe ensuite).
OK, maintenant nous avons cela à l'écart - qu'est-ce qu'une monade ? Eh bien, la façon la plus simple de le dire est - c'est une enveloppe autour d'une certaine valeur. En termes de programmation fonctionnelle, une monade est un foncteur , une structure qui permet de lui appliquer une fonction . C'est une couche supplémentaire d'abstraction entre la valeur et le traitement que nous voulons faire subir à la valeur. Mais cela ne nous dit rien.
Jetons un coup d'œil à la monade la plus simple que vous puissiez imaginer : une implémentation de la Identitymonade :
const Identity = (value) => ({
value: () => value,
map: (fn) => Identity(fn(value)),
});
Prenons l'exemple le plus simple possible :
const addTax = (value) => value * 1.1;
const cartValue = Identity(100);
const cartValueWithTax = cartValue
.map(addTax) // At this point this is Identity(110)
.value(); // Equal to 110 as a number
La Identitymonade a - tout comme la identityfonction dans de nombreuses bibliothèques de programmation fonctionnelle - une logique assez transparente. C'est une monade d'espace réservé, tout comme identityune fonction d'espace réservé. L'application addTaxà notre valeur fonctionne bien pour le scénario ci-dessus, mais réfléchissons à ce qui se passerait si la valeur de notre panier était égale à undefined. Grâce à la merveilleuse façon dont JavaScript fonctionne , nous obtiendrons un fichier NaN.
Habituellement, pour contourner ce problème, la manière la plus intuitive serait d'ajouter une vérification de la valeur à la addTaxfonction. C'est une mauvaise approche. Elle obscurcit le but de la fonction et la rend moins pure. La addTaxfonction ne doit faire qu'une chose et une seule chose : addle Tax.
OK, wiseguy - vous pourriez dire - comment devrions-nous prendre undefineden compte la valeur ? Eh bien, c'est pour cela que nous avons des monades. Nous voulons garder la fonction pure. Nous voulons également que notre logique se comporte différemment en fonction de la valeur que nous transmettons à la fonction. Le meilleur endroit pour définir ce comportement est le foncteur !
Regardons probablement la monade la plus populaire qui soit : Maybe. Cela pourrait être une implémentation de base (je laisse les méthodes habituelles que vous pourriez rencontrer dans une monade comme ofpour plus de clarté):
const Maybe = (value) => ({
value: () => value,
map: (fn) => value === undefined || value === null
? Maybe(null)
: Maybe(fn(value)),
});
const primitiveCart = 100;
const undefinedCart = undefined;
const nullishCart = null;
const maybeCart = Maybe(100);
const maybeUndefinedCart = Maybe(undefined);
const maybeNullishCart = Maybe(null);
addTax(primitiveCart); // boring, 110
addTax(undefinedCart); // NaN
addTax(nullishCart); // 0 - thanks, JavaScript!
maybeCart.map(addTax).value(); // 110
maybeUndefinedCart.map(addTax).value(); // null
maybeNullishCart.map(addTax).value(); // null
Ceci, bien sûr, n'est qu'une égratignure à l'énorme richesse des possibilités qu'apporte l'utilisation des monades. Disons que nous voulons saluer chaque client qui entre dans notre hôtel :
const greet = (name) => `Hello, ${name}!`;
Jetons un coup d'œil à un autre exemple élémentaire - la Optionalmonade :
const Optional = (value) => ({
value: () => value,
orElse: (alternativeValue) => value
? Optional(value)
: Optional(alternativeValue),
map: (fn) => Optional(fn(value)),
});
const firstGuest = "John";
const anonymousGuest = undefined;
greet(firstGuest); // "Hello, John!"
greet(anonymousGuest); // "Hello, undefined" - this is a bit embarrasing
const OptionalWithStrangerFallback = (name) => Optional(name)
.orElse("stranger");
const firstGuestOptional = OptionalWithStrangerFallback(firstGuest);
const anonymousGuestOptional = OptionalWithStrangerFallback(anonymousGuest);
// I really hope you know where this is going at this point
firstGuestOptional.map(greet).value(); "Hello, John!"
anonymousGuestOptional.map(greet).value(); "Hello, stranger!"
J'espère vraiment que cela clarifie les choses avec les monades. Si ce n'est pas le cas, faites-le moi savoir dans les commentaires ! De plus, si vous souhaitez lire plus d'articles sur JavaScript, la programmation fonctionnelle, la vision par ordinateur, l'architecture, la géométrie, les mèmes, le leadership technique ou tout mélange de ce qui précède, assurez-vous de me suivre ici ou sur LinkedIn !
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































