Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Grokking TechTalk #16: Maybe functor in javascript

667 views

Published on

Speaker: Lam Huynh - Senior FrontEnd Developer @ 8Bit Rockstars Co. Ltd

Bio: A Javascript user who is interested in language theory

Description: Introduction to Maybe Functor in Javascript, a concept borrowed from various functional programming languages to help you write cleaner code while still being null-safe.

Published in: Technology
  • Awesome lonely girl looking for fun on webcam with the you now - www.xslideshare.usa.cc
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Grokking TechTalk #16: Maybe functor in javascript

  1. 1. Maybe Functor in Javascript Another approach to null handling 1
  2. 2. 2
  3. 3. Origin of Null Pointer Exception ● Sir Tony Hoare was designing type systems for the language ALGOL W and he put “Null Pointer Exception” as part of the language, because “because it was so easy to implement” ● In 2009, he called it “The Billion Dollar Mistake” 3
  4. 4. What we want: getCountry('vn').getCity('HCMC').population; What we have to do var country = getCountry('vn'); if (country !== null) { var city = country.getCity('HCMC'); if (city !== null) { var population = city.population; } } How do we fight NULL? 4 Drawbacks: ● Looks complicated ● Error-prone, especially when there are many nesting ifs ● Tedious to write ● Declares a lot of useless variables
  5. 5. ● A Functor is a container of a value Introduction to Functor 5 A value A container of value ● A simple Functor can be implemented through an ES6 class class Functor { constructor(value) { this.value = value; } }
  6. 6. One important thing about Functor 6 By definition, a functor needs to implement a map function
  7. 7. Remember Array Map? 7 Let’s look at Array’s map function. var addOne = (x) => x + 1; var square = (x) => x * x; var result = [1, 2, 3] .map(addOne) // [2, 3, 4] .map(square); // [4, 9, 16]
  8. 8. Implement map for Functor 8 class Functor { constructor(value) { this.value = value; } map(fn) { var newValue = fn(this.value); return new Functor(newValue); } }
  9. 9. Let’s see it in action (1) 9 var addOne = (x) => x + 1; var functorOf6 = new Functor(5).map(addOne); // Functor(6)
  10. 10. It can also work with any value, for example, an object: var toUpperCase = (str) => str.toUpperCase(); var exciting = (someName) => someName + ’!!!!!!!’; var value = { name: 'grokking' }; var containerOfValue = new Functor(value) .map(thing => thing.name) // Functor(‘grokking’) .map(toUpperCase) // Functor(‘GROKKING’) .map(exciting); // Functor(‘GROKKING!!!!!!!’) Let’s see it in action (2) 10
  11. 11. Notice that our actual value is still inside the Functor. var functorOf36 = new Functor(5) .map(addOne) // Functor(6) .map(square); // Functor(36) var result = functorOf36 + 100; // Functor(36) + 100 ??????? How to get the value inside Functor 11 Let’s add another method to Functor to extract the value. class Functor { get() { return this.value; } }
  12. 12. var valueInside = new Functor(5) .map(addOne) // Functor(6) .map(square); // Functor(36) .get(); // 36 var toUpperCase = (str) => str.toUpperCase(); var exciting = (someName) => someName + '!!!!!!'; var valueInside = new Functor({ name: 'grokking' }) .map(people => people.name) // Functor(‘grokking’) .map(toUpperCase) // Functor(‘GROKKING’) .map(exciting); // Functor(‘GROKKING!!!!!!!’) .get(); // 'GROKKING!!!!!!!' Now we can get the value inside Functor 12
  13. 13. class Functor { constructor(value) { this.value = value; } map(fn) { var newValue = fn(this.value); return new Maybe(newValue); } get() { return this.value; } } Full implementation of Functor 13
  14. 14. var addOne = (x) => null; // we return Null var square = (x) => x * x; var valueInside = new Functor(1) .map(addOne) // Functor(null) .map(square); // Functor(null * null) ???? .get(); // ???? But we are still affected by NULL 14 The solution is to turn our functor into a Maybe
  15. 15. ● Maybe is a kind of Functor that is Null- friendly. Real magic happens in the map function ● Maybe that contains a real value (not null) is usually called a Just / Some ● Maybe that contains null value is usually called a Nothing / None Introduction to Maybe 15 Maybe(value) = Just(value) Maybe(null) = Nothing
  16. 16. class Maybe { constructor(value) { this.value = value; } map(fn) { if (this.value !== null) { // Magic happens here var newValue = fn(this.value); return new Maybe(newValue); } return new Maybe(null); } getOrElse(fallBackValue) { return (this.value === null) ? this.value : fallBackValue; } } Let’s implement Maybe 16
  17. 17. It’s pretty much the same as Functor’s example. The only difference is that we use getOrElse instead of get var addOne = (x) => x + 1; var square = (x) => x * x; var result = new Maybe(3) .map(addOne) // Maybe(4) .map(square) // Maybe(16) .getOrElse(0); // 16 Maybe in action 17
  18. 18. When Maybe contains NULL, it will not map anymore var result = new Maybe(3) .map(x => null) // Maybe(null) .map(x => x * x) // Maybe(null) .getOrElse(0); // 0 var result = new Maybe(3) .map(x => x + 1) // Maybe(4) .map(x => null) // Maybe(null) .getOrElse(0); // 0 When Null happens 18
  19. 19. Some real world examples var family = { grandma: { mother: { you: 'YOUR NAME HERE' } } }; var you = new Maybe(family.grandma) .map(grandma => grandma.mother) .map(mother => mother.you) .getOrElse('DEFAULT NAME'); // returns “YOUR NAME HERE” var family = { grandma: null }; var you = new Maybe(family.grandma) .map(grandma => grandma.mother) .map(mother => mother.you) .getOrElse('DEFAULT NAME'); // returns “DEFAULT NAME” 19 We can use it to safely access nested objects
  20. 20. Compare with what we used to do 20 var you = family.grandma.mother.you || 'DEFAULT NAME'; var you = 'DEFAULT NAME'; if (family.grandma && family.grandma.mother && family.grandma.mother.you) { you = family.grandma.mother.you; } var you = new Maybe(family.grandma) .map(grandma => grandma.mother) .map(mother => mother.you) .getOrElse('DEFAULT NAME'); Short, but unsafe Safe, but long and nested Safe and flattened
  21. 21. var population = new Maybe(getCountry('vn')) .map(country => country.getCity('HCMC')) .map(city => city.population) .getOrElse(0); Some real world examples var country = getCountry('vn'); if (country !== null) { var city = country.getCity('HCMC'); if (city !== null) { var population = city.population; } } 21 We can rewrite our example earlier Into shorter and flattened code
  22. 22. ● Is just a container of value ● Is a fundamental concept in Functional Programming. From there you can explore Applicative and Monad ● Is a kind of functor that checks null on each map ● Helps flatten your code ● Is used widely in many other languages: - Haskell, Elm: Maybe Recap 22 Maybe Functor
  23. 23. References ● https://github.com/fantasyland/fantasy-land Fantasy Land Specification ● https://cwmyers.github.io/monet.js/ Powerful abstractions for Javascript ● http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html Functor, Applicatives, Monads in pictures ● https://en.wikipedia.org/wiki/Functor (looks scary with all the math) ● http://www.mokacoding.com/blog/functor-applicative-monads-in-pictures/ (Maybe in Swift) ● http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html Java 8 Optional 23

×