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

Functional Design Patterns in JavaScript

Patrik Hedman
September 14, 2014

Functional Design Patterns in JavaScript

Slides from a talk I gave about using different data types and patterns from purely functional programming languages in JavaScript

Patrik Hedman

September 14, 2014
Tweet

Other Decks in Programming

Transcript

  1. Currying ! Composition ! Maybe ! Either ! Promises !

    Functors ! Applicative Functors ! Monads
  2. var curry = function (f) { return function () {

    var slice = [].slice , args = slice.call(arguments); ! return (args.length >= f.length) ? f.apply(null, args) : function () { return curry(f).apply( null, args.concat(slice.call(arguments)) ); } } }
  3. var add = curry(function (a, b) { return a +

    b; }); ! add(1)(2) //=> 3 add(1,2) //=> 3 add()(1)()(2) //=> 3
  4. var extractNames = function (people) { return people.map(function (person) {

    return person.name; }); } ! extractNames([ { name: "Haskell Curry” }, { name: "Moses Schönfinkel" } ]) //=> ["Haskell Curry", "Moses Shönfinkel"]
  5. var map = curry(function (f, xs) { return xs.map(f); });

    ! var prop = curry(function (prop, obj) { return obj[prop]; });
  6. var extractNames = map(function (o) { return upcase(prop("name", o)) });

    ! extractNames([ { name: "Haskell Curry" }, { name: "Moses Schönfinkel" } ]) //=>[ “HASKELL CURRY” , “MOSES SHöNFINKEL” ]
  7. var compose = function () { var fns = [].slice.call(arguments);

    ! return fns.reduce(function (f, g) { return function (x) { return f(g(x)); } }); };
  8. extractNames([ { name: "Haskell Curry" }, { name: "Moses Schönfinkel"

    } ]) //=>[ “!!!HASKELL CURRY” , “!!!MOSES SHöNFINKEL” ]
  9. extractNames([ { name: "Haskell Curry" }, { name: "Moses Schönfinkel"

    } ]) //=>[ "HASKELL CURRY!!!" , "MOSES SHöNFINKEL!!!" ]
  10. Maybe union Maybe { Just { val: * }, Nothing

    } ! Just(2) instanceof Maybe //=> true ! Nothing instanceof Maybe //=> true
  11. Either union Either { Left { l: * }, Right

    { r: * } } ! Left("Error") instanceof Either //=> true ! Right(2) instanceof Either //=> true
  12. Promise data Promise { fork: Function } ! var promise

    = Promise(function (resolve) { setTimeout(function () { resolve("I'm done!"); }, 1000); }); ! promise.fork(function (val) { console.log(val); }); //=> "I'm done"
  13. var promise = Promise(function (resolve) { setTimeout(function () { resolve(2)

    }, 1000) }) ! map(increment, promise) //=> Promise(...) ! promise.fork(function (val) { console.log(val) }) //=> 3
  14. of :: Applicative f => a -> f a ap

    :: Applicative f => f (a -> b) -> f a -> f b
  15. liftA2(concat, ["ha", "heh", "hm"], ["?", "!", "."]) //=> ["ha?","ha!","ha.", "heh?","heh!","heh.",

    "hmm?","hmm!","hmm."] ! liftA2(times, [2, 5, 10], [8, 10, 11]) //=> [16,20,22,40,50,55,80,100,110]
  16. var users = [ { id: 0 , name: "Charles

    Babbage" , desc: "Originated the concept of a programmable computer" }, { id: 1 , name: "Ada Lovelace" , desc: "Wrote the first computer program" } ]
  17. chain(getUser(0), function (p) { return chain(getFriends(p), function (f) { return

    Promise.of(merge(p, {friends: f})) }) }) //=> Promise.of({ id : 0 // , name : "Charles Babbage" // , desc : "…" // , friends : [ // { id: 1 // , name: "Ada Lovelace” // , desc: "…"} // ] // })
  18. do$ { user <- getUser(1) friends <- getFriends(user) ! return

    Promise.of( merge(user, {friends: friends}) ) } //=> Promise.of({ id : 0 // , name : "Charles Babbage" // , desc : "…" // , friends : [ // { id: 1 // , name: "Ada Lovelace” // , desc: "…"} // ] // })
  19. chain([1,2,3], function (x) { return chain([4,5,6], function (y) { return

    [x*y] }) }) //=> [4,5,6,8,10,12,12,15,18] ! do$ { x <- [1,2,3] y <- [4,5,6] ! return [x*y] } //=> [4,5,6,8,10,12,12,15,18]
  20. chain([1,2,3], function (x) { return chain([], function (y) { return

    [x*y] }) }) //=> [] ! do$ { x <- [1,2,3] y <- [] ! return [x*y] } //=> []
  21. chain(Just(2), function (x) { return chain(Just(3), function (y) { return

    Just(x + y) }) }) //=> Just(5) ! do$ { x <- Just(2) y <- Just(3) ! return Just(x + y) } //=> Just(5)
  22. chain(Just(2), function (x) { return chain(Nothing, function (y) { return

    Maybe(x + y) }) }) //=> Nothing ! do$ { x <- Just(2) y <- Nothing ! return Just(x + y) } //=> Nothing
  23. Where to go from here? • Fantasy Land Spec -

    https://github.com/fantasyland/fantasy-land • Rambda - http://ramdajs.com • Folktale - http://folktale.github.io ! • sweet.js - http://sweetjs.org • sweet-fantasies - https://github.com/fantasyland/sweet-fantasies • adt-simple - https://github.com/natefaubion/adt-simple • sparkler - https://github.com/natefaubion/sparkler ! • Purescript - http://www.purescript.org ! • Learn You a Haskell - http://learnyouahaskell.com