Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Apéro fonctionnel

Apéro fonctionnel

Edition Toulousaine pour le DevFest Toulouse

Philippe CHARRIERE

September 28, 2017
Tweet

More Decks by Philippe CHARRIERE

Other Decks in Programming

Transcript

  1. 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();
  2. Container Wrapper public class Container Wrapper <T> { private T

    value; public T getValue() { return this.value; } public Container(T value) { this.value = value; } } ❌ ❌
  3. Wrapper | Exemple Wrapper bottle = new Wrapper<String>(""); bottle.getValue(); //

    Wrapper bob = new Wrapper<String>("Bob"); bob.getValue(); // Bob
  4. Functor public class Functor<T> extends Wrapper { public Functor(T value)

    { super(value); } public <R> Functor<R> map(Function<T,R> fun) { return new Functor<R>(fun.apply((T) this.getValue())); } }
  5. Functor in action Functor<String> bouteilleMagique = new Functor<String>(""); Functor<String> autreBouteille

    = bouteilleMagique .map(contenu -> contenu + "") // plus de poire .map(contenu -> contenu + ""); // plus de poire System.out.println( autreBouteille.getValue() // );
  6. Functor en images .map(contenu -> contenu + "") .map(contenu ->

    contenu + "") .getValue() nouvelle bouteille nouvelle bouteille
  7. html Function<String,String> h1 = value -> "<h1>" + value +

    "</h1>" Function<String,String> body = value -> "<body>" + value + "</body>" Function<String,String> html = value -> "<html>" + value + "</html>" Functor<String> content = new Functor<String>("Hello World") Functor<String> htmlPage = content .map(h1) .map(body) .map(html); System.out.println( htmlPage .getValue()); "<html><body><h1>Hello World</h1></body></html>"
  8. Functor | … dans un functor, dans un … Function<String,

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

    .map(ajouterPoire) nouvelle bouteille nouvelle bouteille
  10. Monad public class Monad<T> extends Wrapper { public Monad(T value)

    { super(value); } public <R> Monad<R> map(Function<T,R> fun) { return new Monad<R>(fun.apply((T) this.getValue())); } public <R> Monad<R> flatMap(Function<T, Monad<R>> fun) { return fun.apply((T) this.getValue()); // on retourne la monade sans la remettre dans un container wrapper } } ❌
  11. Monad | sample Monad<String> bouteilleMagique = new Monad<String>(""); System.out.println( bouteilleMagique

    .flatMap(contenu -> new Monad<String>(contenu + " ")) .flatMap(contenu -> new Monad<String>(contenu + " ")) .getValue() ); //
  12. Functor en images .getValue() nouvelle bouteille nouvelle bouteille .flatMap(contenu ->

    new Monad<String>(contenu + " ")) .flatMap(contenu -> new Monad<String>(contenu + " "))
  13. Monad Identity in RL Monad<Double> prixDeDepart = new Monad<Double>(10000.0); //

    options Function<Double, Double> optionClim = prix -> prix + 2000.0 ; Function<Double, Double> interieurCuir = prix -> prix + 5000.0 ; Function<Double, Double> vitresTeintees = prix -> prix + 3000.0 ; Monad<Double> prixVoitureToutesOptions = prixDeDepart .map(optionClim) .map(interieurCuir) .map(vitresTeintees); System.out.println(prixVoitureToutesOptions.getValue()); // 20 000
  14. 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
  15. TinyToon class TinyToon { public String pseudo; public String avatar;

    public TinyToon(String pseudo, String avatar) { this.pseudo = pseudo; this.avatar = avatar; } }
  16. TinyToons List<TinyToon> tinyToons = Arrays.asList( new TinyToon("Bob", ""), new TinyToon("Jane",

    ""), new TinyToon("Sam", ""), new TinyToon("John", "") ); List<String> myList = tinyToons .stream() .map(toon -> toon.pseudo + toon.avatar) .collect(Collectors.toList()); System.out.println(myList); // [“Bob“, “Jane“, “Sam“, “John“]
  17. TinyToon class TinyToon { public String pseudo; public String avatar;

    public List<TinyToon> buddies; public TinyToon(String pseudo, String avatar) { this.pseudo = pseudo; this.avatar = avatar; } public TinyToon(String pseudo, String avatar, List<TinyToon> buddies) { this.pseudo = pseudo; this.avatar = avatar; this.buddies = buddies; } }
  18. TinyToons List<TinyToon> 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", ""))) ); [ [, ], [, ], [, ], [, ] ]
  19. Je veux les avatars des buddies tinyToons.stream() .flatMap(toon -> toon.buddies.stream())

    .map(toon -> toon.avatar) .collect(Collectors.toList()) [ [, ], [, ], [, ], [, ] ] [“”, ””, ””, ””, ””, ””, ””, ””]
  20. NPE

  21. 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
  22. 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
  23. NPE avant Function<Integer, TinyToon> getToon = key -> { Map<Integer,

    TinyToon> tinyToons = new HashMap<Integer, TinyToon>() {{ 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)
  24. NPE après (avec Java 8) Function<Integer, Optional<TinyToon>> getMayBeToon = key

    -> { Map<Integer, TinyToon> tinyToons = new HashMap<Integer, TinyToon>() {{ 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)); };
  25. 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[]
  26. je colle du optional partout class TinyToon { public Optional<String>

    pseudo; public Optional<String> avatar; public TinyToon(String pseudo, String avatar) { this.pseudo = Optional.ofNullable(pseudo); this.avatar = Optional.ofNullable(avatar); } }
  27. –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. ”
  28. Either, another ❤ monad there is no Either with Java

    8 A type with 2 sub-types Left & Right
  29. 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