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

Functional Design Patterns in JavaScript

Avatar for Patrik Hedman 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

Avatar for Patrik Hedman

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