Slide 1

Slide 1 text

Apéro fonctionnel Edition Toulousaine

Slide 2

Slide 2 text

Container

Slide 3

Slide 3 text

Bob public class Human { private String name; public Human(String name) { this.name = name; } public String getName() { return name; } } Human bob = new Human("Bob"); bob.getName();

Slide 4

Slide 4 text

Container Wrapper ❌

Slide 5

Slide 5 text

Container Wrapper public class Container Wrapper { private T value; public T getValue() { return this.value; } public Container(T value) { this.value = value; } } ❌ ❌

Slide 6

Slide 6 text

Wrapper | Exemple Wrapper bottle = new Wrapper(""); bottle.getValue(); // Wrapper bob = new Wrapper("Bob"); bob.getValue(); // Bob

Slide 7

Slide 7 text

Functor

Slide 8

Slide 8 text

Functor public class Functor extends Wrapper { public Functor(T value) { super(value); } public Functor map(Function fun) { return new Functor(fun.apply((T) this.getValue())); } }

Slide 9

Slide 9 text

Functor in action Functor bouteilleMagique = new Functor(""); Functor autreBouteille = bouteilleMagique .map(contenu -> contenu + "") // plus de poire .map(contenu -> contenu + ""); // plus de poire System.out.println( autreBouteille.getValue() // );

Slide 10

Slide 10 text

Functor en images .map(contenu -> contenu + "") .map(contenu -> contenu + "") .getValue() nouvelle bouteille nouvelle bouteille

Slide 11

Slide 11 text

Dans la vraie vie

Slide 12

Slide 12 text

html Function h1 = value -> "

" + value + "

" Function body = value -> "" + value + "" Function html = value -> "" + value + "" Functor content = new Functor("Hello World") Functor htmlPage = content .map(h1) .map(body) .map(html); System.out.println( htmlPage .getValue()); "

Hello World

"

Slide 13

Slide 13 text

Functor | … dans un functor, dans un … Function> ajouterPoire = contenu -> new Functor(contenu + ""); bouteilleMagique .map(contenu -> new Functor(contenu + "")) .getValue() // Functor@3e3abc88 // Type attendu: Functor> // Puis: Functor>> etc...

Slide 14

Slide 14 text

Functor | … dans un functor, dans un … .map(ajouterPoire) .map(ajouterPoire) nouvelle bouteille nouvelle bouteille

Slide 15

Slide 15 text

Monad ou comment sortir les poires correctement

Slide 16

Slide 16 text

Monad public class Monad extends Wrapper { public Monad(T value) { super(value); } public Monad map(Function fun) { return new Monad(fun.apply((T) this.getValue())); } public Monad flatMap(Function> fun) { return fun.apply((T) this.getValue()); // on retourne la monade sans la remettre dans un container wrapper } } ❌

Slide 17

Slide 17 text

Monad | sample Monad bouteilleMagique = new Monad(""); System.out.println( bouteilleMagique .flatMap(contenu -> new Monad(contenu + " ")) .flatMap(contenu -> new Monad(contenu + " ")) .getValue() ); //

Slide 18

Slide 18 text

Functor en images .getValue() nouvelle bouteille nouvelle bouteille .flatMap(contenu -> new Monad(contenu + " ")) .flatMap(contenu -> new Monad(contenu + " "))

Slide 19

Slide 19 text

J’achète une voiture

Slide 20

Slide 20 text

Monad Identity in RL Monad prixDeDepart = new Monad(10000.0); // options Function optionClim = prix -> prix + 2000.0 ; Function interieurCuir = prix -> prix + 5000.0 ; Function vitresTeintees = prix -> prix + 3000.0 ; Monad prixVoitureToutesOptions = prixDeDepart .map(optionClim) .map(interieurCuir) .map(vitresTeintees); System.out.println(prixVoitureToutesOptions.getValue()); // 20 000

Slide 21

Slide 21 text

Vous utilisez déjà des Monad(e)s

Slide 22

Slide 22 text

un stream a une map et une flatMap! … Donc? Stream c’est une api qui utilise les lambdas et qui permet de faire des choses sympas avec les collections

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

.map()

Slide 25

Slide 25 text

TinyToon class TinyToon { public String pseudo; public String avatar; public TinyToon(String pseudo, String avatar) { this.pseudo = pseudo; this.avatar = avatar; } }

Slide 26

Slide 26 text

TinyToons List tinyToons = Arrays.asList( new TinyToon("Bob", ""), new TinyToon("Jane", ""), new TinyToon("Sam", ""), new TinyToon("John", "") ); List myList = tinyToons .stream() .map(toon -> toon.pseudo + toon.avatar) .collect(Collectors.toList()); System.out.println(myList); // [“Bob“, “Jane“, “Sam“, “John“]

Slide 27

Slide 27 text

.flatMap()

Slide 28

Slide 28 text

TinyToon class TinyToon { public String pseudo; public String avatar; public List buddies; public TinyToon(String pseudo, String avatar) { this.pseudo = pseudo; this.avatar = avatar; } public TinyToon(String pseudo, String avatar, List buddies) { this.pseudo = pseudo; this.avatar = avatar; this.buddies = buddies; } }

Slide 29

Slide 29 text

TinyToons List tinyToons = Arrays.asList( new TinyToon("Bob", "", Arrays.asList( new TinyToon("Ted", ""), new TinyToon("Polo", ""))), new TinyToon("Jane", "", Arrays.asList( new TinyToon("Zed", ""), new TinyToon("Grou", ""))), new TinyToon("Sam", "", Arrays.asList( new TinyToon("Kate", ""), new TinyToon("Nike", ""))), new TinyToon("John", "", Arrays.asList( new TinyToon("Ray", ""), new TinyToon("Zoe", ""))) ); [ [, ], [, ], [, ], [, ] ]

Slide 30

Slide 30 text

Je veux les avatars des buddies tinyToons.stream() .flatMap(toon -> toon.buddies.stream()) .map(toon -> toon.avatar) .collect(Collectors.toList()) [ [, ], [, ], [, ], [, ] ] [“”, ””, ””, ””, ””, ””, ””, ””]

Slide 31

Slide 31 text

NPE

Slide 32

Slide 32 text

Le problème: c’est Null Ça ne veut pas dire grand chose Ce n’est pas vraiment un type Et pourtant, tout type en Java peut être null

Slide 33

Slide 33 text

Optional permet de modéliser null Optional<> a 2 sous types / sous états Optional.of() Optional.empty() // pas de Optional<> a 2 sous types / sous états Optional.of() Optional.empty() // pas de

Slide 34

Slide 34 text

Optional Optional.empty() Optional.of()

Slide 35

Slide 35 text

mais retrouvons nos tiny toons

Slide 36

Slide 36 text

NPE avant Function getToon = key -> { Map tinyToons = new HashMap() {{ put(1, new TinyToon("Bob", "")); put(2, new TinyToon("Jane", "")); put(3, new TinyToon("Sam", "")); put(4, new TinyToon("John", "")); }}; return tinyToons.get(key); }; System.out.println(getToon.apply(2).avatar); System.out.println(getToon.apply(4).avatar); System.out.println(getToon.apply(6).avatar); //⚠ le toon 6 n’existe pas > > > Exception in thread "main" java.lang.NullPointerException at SearchToons.main(SearchToons.java:20)

Slide 37

Slide 37 text

NPE après (avec Java 8) Function> getMayBeToon = key -> { Map tinyToons = new HashMap() {{ put(1, new TinyToon("Bob", "")); put(2, new TinyToon("Jane", "")); put(3, new TinyToon("Sam", "")); put(4, new TinyToon("John", "")); }}; return Optional.ofNullable(tinyToons.get(key)); };

Slide 38

Slide 38 text

NPE après (avec Java 8) getMayBeToon.apply(6) // Optional.empty getMayBeToon.apply(3) // Optional[TinyToon@3e3abc88] getMayBeToon.apply(6).map(toon -> toon.avatar) // Optional.empty getMayBeToon.apply(3).map(toon -> toon.avatar) // Optional[]

Slide 39

Slide 39 text

je colle du optional partout class TinyToon { public Optional pseudo; public Optional avatar; public TinyToon(String pseudo, String avatar) { this.pseudo = Optional.ofNullable(pseudo); this.avatar = Optional.ofNullable(avatar); } }

Slide 40

Slide 40 text

Optional + flatMap getMayBeToon.apply(3).map(toon -> toon.avatar); //Optional[Optional[]] getMayBeToon.apply(3).flatMap(toon -> toon.avatar); //Optional[] ⚠ Optional

Slide 41

Slide 41 text

–Probablement Wikipedia “In category theory, the concept of catamorphism (from Greek: κατά = downwards or according to; μορφή = form or shape) denotes the unique homomorphism from an initial algebra into some other algebra. ”

Slide 42

Slide 42 text

Either, another ❤ monad there is no Either with Java 8 A type with 2 sub-types Left & Right

Slide 43

Slide 43 text

pas bon - bon Either.left( ) Either.right()

Slide 44

Slide 44 text

Catamorphisme avec Either toInt.apply("40").map(value -> value + 2) .cata(err -> { System.out.println(" ouille"); return 0; }, res -> { // right System.out.println(" yes: " + res); return res; }); // yes: 42 toInt.apply("quarante-deux").map(value -> value + 2) .cata(err -> { System.out.println(" ouille"); return 0; }, res -> {// right System.out.println(" yes: " + res); return res; }); // ouille