Successfully reported this slideshow.
Your SlideShare is downloading. ×

Awesomely descriptive JavaScript with monads

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 79 Ad

Awesomely descriptive JavaScript with monads

Download to read offline

"Can unfamiliar pattern from world of statically typed functional languages improve JavaScript world? For sure YES! The elastic nature of JavaScript can handle great ideas from many alien worlds. With a little help of modern tools like ​monet.js​ and ​TypeScript​ we can achieve awesomely descriptive aesthetics of our code and drop some imperative bloat."

On 19 march 2016 Kuba Strojewski from Evojam gave a speech about monads on meet.js summit JavaScript Conference. Here's his slide deck.

"Can unfamiliar pattern from world of statically typed functional languages improve JavaScript world? For sure YES! The elastic nature of JavaScript can handle great ideas from many alien worlds. With a little help of modern tools like ​monet.js​ and ​TypeScript​ we can achieve awesomely descriptive aesthetics of our code and drop some imperative bloat."

On 19 march 2016 Kuba Strojewski from Evojam gave a speech about monads on meet.js summit JavaScript Conference. Here's his slide deck.

Advertisement
Advertisement

More Related Content

Recently uploaded (20)

Advertisement

Awesomely descriptive JavaScript with monads

  1. 1. Awesomely descriptive JavaScript with Monads
  2. 2. Theory
  3. 3. Monad laws return a >>= f ≡ f a m >>= return ≡ m (m >>= f) >>= g ≡ m >>= (x -> f x >>= g)
  4. 4. Monad laws
  5. 5. Practical theory
  6. 6. V E G E T A B L E A L U E
  7. 7. P => M<S> f
  8. 8. => unit P => M<P>
  9. 9. ( , ) => bind ( M<P> , P => M<S> ) => M<S>
  10. 10. ( M<P> , P => M<S> ) => M<S>M<P> P => M<S> M<S> extract value bind function m(x) x x => m(y) m(y) bind
  11. 11. Monad laws (JavaScript) bind( unit(v) , f ) ≡ f(v) bind( monad , unit ) ≡ monad bind( bind( monad , f ) , g ) ≡ bind( monad, v => bind( f(v) , g ) )
  12. 12. monet.js
  13. 13. UNIT Identity(x) Maybe.Some(x) Maybe.None() Either.Left(e) Either.Right(x) List(x, Nil) monad.bind(f) monad.flatMap(f) monad.chain(f) BIND
  14. 14. Monad laws (monet.js / Identity) Identity(v).flatMap(f) ≡ f(v) id.flatMap(Identity) ≡ id id.flatMap(f).flatMap( g ) ≡ id.flatMap(v => f(v).flatMap(g))
  15. 15. Practice: Identity
  16. 16. UNIT Identity(x) Maybe.Some(x) Maybe.None() Either.Left(e) Either.Right(x) List(x, Nil) monad.bind(f) monad.flatMap(f) monad.chain(f) BIND
  17. 17. var pepperInABowl = getBowlOf('pepper', 'red'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  18. 18. const mixInABowl = getBowlOf('pepper') .flatMap(slice) .faltMap(silcedPepper => getBowlOf('tomato') .flatMap(slice) .faltMap(mixedTomato => mix(silcedPepper , mixedTomato)));
  19. 19. But HOW ?
  20. 20. interface Bowl<V> { get(): V; } getBowlOf<V>(name: string): Bowl<V>; slice<S>(vegetable: Vege): Bowl<S>; mix<M>(...ingredients): Bowl<M>;
  21. 21. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  22. 22. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  23. 23. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  24. 24. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  25. 25. monet.js Identity( … )
  26. 26. type Op<A, B> = (val:A) => Bowl<B>; interface Bowl<V> { get(): V; flatMap<S>(f: Op<V, S>): Bowl<S>; }
  27. 27. goo.gl/dh9DrZ
  28. 28. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  29. 29. const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice);
  30. 30. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  31. 31. const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice); const slicedTomatoInABowl = getBowlOf('tomato').flatMap(slice);
  32. 32. var pepperInABowl = getBowlOf('pepper'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  33. 33. const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice); const mixInABowl = getBowlOf('pepper') .flatMap(slice) .faltMap(silcedPepper => mix(silcedPepper , slicedPepperInABowl.get()));
  34. 34. const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice); const mixInABowl = getBowlOf('pepper') .flatMap(slice) .flatMap(silcedPepper => slicedPepperInABowl .flatMap(mixedTomato => mix(silcedPepper , mixedTomato)));
  35. 35. const mixInABowl = getBowlOf('pepper') .flatMap(slice) .faltMap(silcedPepper => getBowlOf('tomato') .flatMap(slice) .flatMap(mixedTomato => mix(silcedPepper , mixedTomato)));
  36. 36. var pepperInABowl = getBowlOf('pepper', 'red'); var pepper = pepperInABowl.get(); var slicedPepperInABowl = slice(pepper); var tomatoInABowl = getBowlOf('tomato'); var tomato = tomatoInABowl.get(); var slicedTomatoInABowl = slice(tomato); var slicedPepper = slicedPepperInABowl.get(); var slicedTomato = slicedTomatoInABowl.get(); var mixInABowl = mix(slicedPepper, slicedTomato);
  37. 37. Practice: Maybe
  38. 38. UNIT Identity(x) Maybe.Some(x) Maybe.None() Either.Left(e) Either.Right(x) List(x, Nil) monad.bind(f) monad.flatMap(f) monad.chain(f) BIND
  39. 39. let spiceMix; const salt = getSpice('salt'); let coriander = getSpice('coriander'); if (coriander) { coriander = crush(coriander); } if (coriander && salt && isPowdered(salt)) { spiceMix = mixSpice(salt , coriander); } spiceMix = vegeta;
  40. 40. let spiceMix; const salt = getSpice('salt'); let coriander = getSpice('coriander'); if (coriander) { coriander = crush(coriander); } if (coriander && salt && isPowdered(salt)) { spiceMix = mixSpice(salt , coriander); } spiceMix = vegeta;
  41. 41. const spiceMix = getSpice('salt').filter(isPowdered) .flatMap(salt => getSpice('coriander').map(crush) .flatMap(coriander => mixSpice(salt , coriadner))) .orJust(vegeta);
  42. 42. But HOW ?
  43. 43. getSpice<V>(name: string): Maybe<V>; crush(spice: S): S; isPowdered(spice: S): boolean;
  44. 44. getSpice<V>(name: string): Maybe<V>; crush(spice: S): S; isPowdered(spice: S): boolean;
  45. 45. getSpice<V>(name: string): Maybe<V>; crush(spice: S): S; isPowdered(spice: S): boolean;
  46. 46. monet.js Maybe
  47. 47. interface Maybe<T> { flatMap<V>(fn: (val: T) => Maybe<V>): Maybe<V>; map<V>(fn: (val: T) => V): Maybe<V>; filter(fn: (val: T) => boolean): Maybe<T>; orJust(val: T): T; }
  48. 48. const silkySalt = getSpice('salt').filter(isPowdered); const crushedCoriander = getSpice('coriander').map(crush); const spiceMixMaybe = silkySalt.flatMap(salt => crushedCoriander.flatMap(coriander => mixSpice( salt , coriadner ))); const spiceMix = spiceMixMaybe.orJust(vegeta);
  49. 49. const crushedCoriander = getSpice('coriander').map(crush); const spiceMixMaybe = getSpice('salt').filter(isPowdered).flatMap(salt => crushedCoriander.flatMap(coriander => mixSpice( salt , coriadner ))); const spiceMix = spiceMixMaybe.orJust(vegeta);
  50. 50. const spiceMixMaybe = getSpice('salt').filter(isPowdered).flatMap(salt => getSpice('coriander').map(crush).flatMap(coriander => mixSpice( salt , coriadner ))); const spiceMix = spiceMixMaybe.orJust(vegeta);
  51. 51. const spiceMixMaybe = getSpice('salt').filter(isPowdered) .flatMap(salt => getSpice('coriander').map(crush) .flatMap(coriander => mixSpice( salt , coriadner ))); const spiceMix = spiceMixMaybe.orJust(vegeta);
  52. 52. const spiceMix = getSpice('salt').filter(isPowdered) .flatMap(salt => getSpice('coriander').map(crush) .flatMap(coriander => mixSpice( salt , coriadner ))); .orJust(vegeta)
  53. 53. const spiceMix = getSpice('salt') .filter(isPowdered) .flatMap(salt => getSpice('coriander') .map(crush) .flatMap(coriander => mixSpice(salt , coriadner))) .orJust(vegeta);
  54. 54. null
  55. 55. getSpice<V>(name: string): Maybe<V> { let spice = locker.get(name); if (spice != null) { return Some(spice); } return None(); }
  56. 56. getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return Some(spice); } return None(); }
  57. 57. getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return … ? } return None(); }
  58. 58. monet.js Some( … )
  59. 59. getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return Some(spice); } return None(); }
  60. 60. monet.js None()
  61. 61. getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return Some(spice); } return None(); }
  62. 62. monet.js .fromNull()
  63. 63. getSpice<V>(name: string): Maybe<V> { return Maybe.fromNull( locker.get(name) ); }
  64. 64. goo.gl/cvGVeo
  65. 65. const saladBowl = mixInABowl .flatMap(mixedVegetables => mix(mixedVegetables, spiceMix));
  66. 66. e a t i t
  67. 67. Monads Identity Maybe Either Validation List NEL Reader Free IO ?
  68. 68. Monads Identity Maybe Either Validation List NEL Reader Free IO Promise
  69. 69. T H X
  70. 70. Jakub . Strojewski @gmail.com u l f r y k

Editor's Notes

  • Story about doing things in kitchen.
  • var pepperInABowl = getBowlOf('pepper', 'red');
    var pepper = pepperInABowl.get();
    var slicedPepperInABowl = slice(pepper);
  • var tomatoInABowl = getBowlOf('tomato');
    var tomato = tomatoInABowl.get();
    var slicedTomatoInABowl = slice(tomato);
  • var slicedPepper = slicedPepperInABowl.get();
    var slicedTomato = slicedTomatoInABowl.get();
  • var mixInABowl = mix(slicedPepper, slicedTomato);
  • Part of implementation
  • interface Bowl<V> {
    get(): V;
    }
  • You can play around :)
  • var pepperInABowl = getBowlOf('pepper', 'red');
    var pepper = pepperInABowl.get();
    var slicedPepperInABowl = slice(pepper);
  • var tomatoInABowl = getBowlOf('tomato');
    var tomato = tomatoInABowl.get();
    var slicedTomatoInABowl = slice(tomato);
  • var slicedPepper = slicedPepperInABowl.get();
    var slicedTomato = slicedTomatoInABowl.get();
    var mixInABowl = mix(slicedPepper, slicedTomato);
  • statefull
    imperative
  • simple
    accurate
  • Article intro to monads

×