Your SlideShare is downloading. ×
Devoxx France 2014 - La puissance de mon Monoïde est supérieure à 9000
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Devoxx France 2014 - La puissance de mon Monoïde est supérieure à 9000

1,177
views

Published on


0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,177
On Slideshare
0
From Embeds
0
Number of Embeds
29
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. @benoit_lemoine #monoid9000 La puissance de mon monoïde est supérieure à 9000 @benoit_lemoine Xebia Développeur
  • 2. @benoit_lemoine #monoid9000 Qu’est ce qu’un monoïde ? Un monoïde est un magma unifère associatif Non, en vrai, c’est quoi un monoïde ?
  • 3. @benoit_lemoine #monoid9000 TypeScript • Syntaxe proche de JavaScript • Sucre syntaxique et classe • Typage statique • Langage cool
  • 4. @benoit_lemoine #monoid9000 Il était une fois…
  • 5. @benoit_lemoine #monoid9000 class Guy {! constructor(public power:number) {}! ! //Égalité structurelle! equals(g:Guy): boolean {! return g.power == this.power! }! }! ! var boo = new Guy(8500)! console.log(boo.power) //affiche 8500! Modélisons Boo
  • 6. @benoit_lemoine #monoid9000 Mais la Terre est fournie avec son protecteur
  • 7. @benoit_lemoine #monoid9000 var boo = new Guy(8500);! var goku = new Guy(4000);! ! function fight(guy1:Guy, guy2:Guy):Guy {! return guy1.power > guy2.power ? guy1 : guy2;! };! ! var winner = fight(goku, boo);! console.log(winner); ! // affiche boo, car il est de loin le plus fort! ! Modélisons Goku et le combat
  • 8. @benoit_lemoine #monoid9000 Goku a perdu !
  • 9. @benoit_lemoine #monoid9000 Appel à un ami !
  • 10. @benoit_lemoine #monoid9000 var boo = new Guy(8500);! var goku = new Guy(4000);! var vegeta = new Guy(3900);! ! function fusion(guy1:Guy, guy2:Guy):Guy {! return new Guy(guy1.power + guy2.power);! }! ! var bejito = fusion(goku, vegeta); // puissance de 7900! ! var winner = fight(bejito, boo)! console.log(winner) ! // affiche toujours boo, car il est toujours le plus fort! Modélisons la fusion
  • 11. @benoit_lemoine #monoid9000 Bejito est vaincu !
  • 12. @benoit_lemoine #monoid9000 Augmentation du nombre de ressources
  • 13. @benoit_lemoine #monoid9000 var goten = new Guy(2000);! var trunks = new Guy(2500);! ! var gotenks = fusion(goten, trunks); // puissance de 4500! var gobejitenks = fusion(gotenks, bejito); // puissance de 12400! ! fight(gobejitenks, boo); // gobejitenks gagne! Fusion partout
  • 14. @benoit_lemoine #monoid9000 La victoire était assurée car
  • 15. @benoit_lemoine #monoid9000 function fusion(guy1:Guy, guy2:Guy):Guy {! return new Guy(guy1.power + guy2.power);! }! Loi de composition interne fusion est une fonction… •  …qui prend 2 paramètres du même type Guy! •  …qui renvoie une valeur du même type Guy!
  • 16. @benoit_lemoine #monoid9000 function fusion(guy1:Guy, guy2:Guy):Guy {! return new Guy(guy1.power + guy2.power);! }! ! var fusionned1 = fusion(fusion(goku, vegeta), goten);! var fusionned2 = fusion(goku, fusion(vegeta, goten));! ! console.log(fusionned1.equals(fusionned2)); //affiche true! Associativité
  • 17. @benoit_lemoine #monoid9000 var gobejitenks = [goku, vegeta, goten, trunks].reduce(fusion)! Loi de composition interne associative Rend plus lisible les fold/inject/reduce!
  • 18. @benoit_lemoine #monoid9000 var goku = new Guy(4000);! var mrSatan = new Guy(0);! ! var gotan = fusion(goku, mrSatan);! var saku = fusion(mrSatan, goku);! ! console.log(gotan.equals(saku)) //affiche true! console.log(gotan.equals(goku)) //affiche true! console.log(saku.equals(goku)) //affiche true! Élément neutre de fusion!
  • 19. @benoit_lemoine #monoid9000 On a un monoïde ! Un monoïde est un ensemble muni d’une loi de composition interne associative et d’un élément neutre • Ensemble des Guy! • fusion! • new Guy(0)!
  • 20. @benoit_lemoine #monoid9000 ET ? À quoi ça sert ?
  • 21. @benoit_lemoine #monoid9000 La fusion, ça prend du temps
  • 22. @benoit_lemoine #monoid9000 Q, Librairie de promesses • Exécution séquentielle de code asynchrone • Composabilité • Les promesses, c’est cool
  • 23. @benoit_lemoine #monoid9000 //La fusion éxecutera la callback de promesse après 0.5 seconde! function fusion(guy1:Guy,guy2:Guy):Q.IPromise<Guy> {! var deferred = Q.defer();! ! setTimeout(function() {! deferred.resolve(new Guy(guy1.power + guy2.power))! }, 500);! ! return deferred.promise;! };! ! fusion différée!
  • 24. @benoit_lemoine #monoid9000 var boo = new Guy(8500);! var goku = new Guy(4000);! var vegeta = new Guy(3500);! ! var promiseForBejito:Q.IPromise<Guy> = fusion(goku, vegeta);! ! promiseForBejito.done(function(bejito:Guy) {! // affiche boo, une fois que la fusion est finie! console.log(fight(bejito, boo));! });! Exemple!
  • 25. @benoit_lemoine #monoid9000 fusion n’est plus une loi de composition interne Le type de retour Q.IPromise<Guy> n'est pas le même que celui d'entrée, Guy!
  • 26. @benoit_lemoine #monoid9000 function fusionPromise(guy1:Q.IPromise<Guy>,! guy2:Q.IPromise<Guy>):Q.IPromise<Guy> {! return Q.all([guy1, guy2]).then((guys) => fusion(guys[0], guys[1]))! }! ! var noHero:Q.IPromise<Guy> = Q(new Guy(0));! var heroes = [goku, vegeta, goten, trunks];! var promiseForHeroes:Array<Q.IPromise<Guy>> = heroes.map(Q);! var promiseForGobejitenks = promiseForHeroes.reduce(fusionPromise, noHero);! ! promiseForGobejitenks.done((gobejitenks) => {! // gobejitenks gagne, après 1.5 secondes! console.log(fight(gobejitenks, boo))! });! Retour de la loi de composition interne!
  • 27. @benoit_lemoine #monoid9000 Algorithme de parcours en arbre Si la liste contient Alors… 0 élément … on renvoie l’élément neutre 1 élément … on renvoie l’élément de la liste 2 éléments … on renvoie la fusion des deux élements Plus de 2 éléments … on divise la liste en 2 parts et on exécute l'algorithme ici défini sur chacune des parties, avant de fusionner leurs résultats
  • 28. @benoit_lemoine #monoid9000 function reduceFusion(coll:Array<Q.IPromise<Guy>>):Q.IPromise<Guy> {! var elementsCount = coll.length;! if(elementsCount == 2) {! return fusionPromise(coll[0], coll[1]);! } else if(elementsCount == 1) {! return fusionPromise[0];! } else if (elementsCount == 0) {! return Q(new Guy(0))! } else {! var halfSize = elementsCount / 2! var half1Combined = reduceFusion(coll.slice(0, halfSize));! var half2Combined = reduceFusion(coll.slice(halfSize, elementsCount));! return fusionPromise(half1Combined, half2Combined);! }! };! Attention, fonction récursive à l’horizon!
  • 29. @benoit_lemoine #monoid9000 var promiseForHeroes = [goku, vegeta, goten, trunks].map(Q)! reduceFusion(promiseForHeroes).done(function(gobejitenks) {! //gobejitenks gagne, après seulement 1s, et plus 1.5 s! console.log(fight(gobejitenks, boo));! });! Usage!
  • 30. @benoit_lemoine #monoid9000 Optimisation sous forme de parcours d’arbre
  • 31. @benoit_lemoine #monoid9000 Que fallait-il pour paralléliser ? Une loi de composition interne… •  …associative •  …avec un élément neutre Un monoïde !
  • 32. @benoit_lemoine #monoid9000 Abstraction de monoïde! interface Monoid<T> {! ZERO:T; //element neutre! combine:(a:T, b:T) => T //loi de composition interne! } !
  • 33. @benoit_lemoine #monoid9000 Reduce, parallèlisation et monoïde! var reduceMonoid = function<T>(m:Monoid<T>, coll:Array<T>):T {! var elementsCount = coll.length;! if(elementsCount == 2) {! return m.combine(coll[0], coll[1]);! } else if(elementsCount == 1) {! return coll[0];! } else if (elementsCount == 0) {! return m.ZERO! } else {! var halfSize = elementsCount / 2! var firstHalf = reduceMonoid(m, coll.slice(0, halfSize));! var secondHalf = reduceMonoid(m, coll.slice(halfSize, elementsCount));! return m.combine(firstHalf, secondHalf);! }! };!
  • 34. @benoit_lemoine #monoid9000 Fusion et Reduce Monoïde! var monoidOfPromiseOfGuy:Monoid<Q.IPromise<Guy>> = {! ZERO: Q(new Guy(0)),! combine: fusionPromise! };! ! var promiseForHeroes = [goku,vegeta, goten, trunks].map(Q)! var promiseForGobejitenks =! reduceMonoid(monoidOfPromiseOfGuy, promiseForHeroes);!
  • 35. @benoit_lemoine #monoid9000 Quand on commence à penser monoïde! var monoidOfBetterGuy: Monoid<Guy> = {! ZERO:new Guy(0),! combine:fight! };! var heroes = [goku,vegeta, boo, goten, trunks];! var winnerOfBattleRoyale =! reduceMonoid(monoidOfBetterGuy, heroes); // renvoit boo! On en voit partout!
  • 36. @benoit_lemoine #monoid9000 Au fond, les monoïdes sont partout Quelques exemples : (ensemble, opération, élément neutre) • (number, +, 0) • (number, *, 1) • (number > 0, max, 0) • (string, '', +) • (array, [], concat)
  • 37. @benoit_lemoine #monoid9000 En résumé – Le monoïde •  Améliore la lisibilité •  Permet le parcours de liste comme un arbre •  Permet la parallélisation des traitements
  • 38. @benoit_lemoine #monoid9000 En résumé – Les mathématiques Les gros mots des matheux couvrent des abstractions… •  … abstractions qui permettent la réutilisabilité d’un concept •  … abstractions qui imposent un « contrat » aux ensembles auxquels elles s’appliquent, comme nos interfaces
  • 39. @benoit_lemoine #monoid9000 Des questions ?

×