What every hipster should know about

Functional Programming

@bodil

The Great Paradigms

Stand back!
We know regular expressions.
A monad is just a monoid in the category of endofunctors.
What's the problem?
I am Oleg Kiselyov.
I bring greetings from my planet.

tl;dr

Applicative functors.
You probably haven't heard of them.
You need to write an interface
for that implementation!
I use Haskell.
You probably wouldn't understand it.
CATEGORY THEORY
ALONZO CHURCH
HASKELL CURRY
SUPER LAMBDA BROS.
JOHN McCARTHY
FIRST CLASS FUNCTIONS
            function hello(): string {
              return "Hello everypony!";
            }
          
FUNCTORS

Functors

A functor is a collection of X that can apply a function f : X → Y over itself to create a collection of Y.

            function CAPS(s: string): string {
              return s.toUpperCase();
            }

            /* f : X → Y */
            function map(func: (a: any) => any, list: any[]): any[] {
              ...
            }

            var ponies = [ "Rainbow Dash", "Pinkie Pie", "Twilight Sparkle" ];
          
            var ponies = [ "Rainbow Dash", "Pinkie Pie", "Twilight Sparkle" ];
          
            function tooCool(s: string): bool {
              return s != "Rainbow Dash";
            }

            function filter(func: (any) => bool, list: any[]) {
              var new_list = [], i;
              for (i = 0; i < list.length; i++) {
                ...
              }
              return new_list;
            }
          
REDUCTION
            var ponies = [ "Rainbow Dash", "Pinkie Pie", "Twilight Sparkle" ];
          
            function add(a, b) {
              return a + b;
            }

            function reduce(func: (a, b) => any, list: any[], initial) {
              ...
            }
          
            function CAPS(s: string): string {
              return s.toUpperCase();
            }

            function map(func, list: any[]) {
             return list.map(func);
            }

            var ponies = [ "Rainbow Dash", "Pinkie Pie", "Twilight Sparkle" ];
          
            function reduce(func: (a, b) => any, list: any[], initial) {
              var result = initial, i: number;
              for (i = 0; i < list.length; i++) {
                result = func(result, list[i]);
              }
              return result;
            }
          
HIGHER ORDER FUNCTIONS
            function reduce(func, list: any[], initial) {
              return list.reduce(func, initial);
            }

            var ponies = [ "Rainbow Dash", "Pinkie Pie", "Twilight Sparkle" ];
          
            function CAPS(s: string): string {
              return s.toUpperCase();
            }

            function shoutyMapReducer(a: string[], b: string): string[] {
              return a.concat([b.toUpperCase()]);
            }
          
COMBINATORS
            function square(x: number) {
              return x * x;
            }
          
            var pinkie = {
              name: "Pinkie Pie",
              type: "Pegasus Pony"
            };

            function ponyType(pony): string {
              return pony.type;
            }
          
COMPOSITION
          
            function CAPS(s: string): string {
              return s.toUpperCase();
            }

            function hi(s: string) {
              return "Hello " + s + "!";
            }
          
APPLICATIVE FUNCTORS
            function CAPS(s: string): string {
              return s.toUpperCase();
            }

            function hi(s: string) {
              return "Hello " + s + "!";
            }

            function add(...args: number[]) {
              return args.reduce(function(a,b) { return a + b; })
            }
          
            function amap1(func: Function, args: any[], lists: any[]) {
              var new_list = [], list, i;
              if (lists.length) {
                list = lists[0];
                for (i = 0; i < list.length; i++) {
                  new_list = new_list.concat(amap1(func, args.concat([list[i]]), lists.slice(1)));
                }
                return new_list;
              } else {
                return func.apply(null, args);
              }
            }

            function amap(funcs: Function[], ...lists: any[]) {
              var new_list = [], i;
              for (i = 0; i < funcs.length; i++) {
                new_list = new_list.concat(amap1(funcs[i], [], lists));
              }
              return new_list;
            }

            var ponies = [ "Rainbow Dash", "Pinkie Pie", "Twilight Sparkle" ];
          
CURRYING

Currying

The act of transforming a function of several arguments into a chain of functions of one argument that will yield the same result when called in sequence with the same arguments.

f(x, y, z) = g(x)(y)(z)

Currying

Named for Haskell Curry, who rediscovered the concept originally originated by Moses Schönfinkel.

Thus a more accurate name would be schönfinkeling.

            function curry(func: Function, arity: number) {
              return function(x) {
                if (arity === 1) {
                  return func(x);
                } else {
                  return curry(func.bind(null, x), arity - 1);
                }
              };
            }

            function add(...args: number[]) {
              return args.reduce(function(a,b) { return a + b; })
            }
          
            function partial(func: Function, ...curriedArgs: any[]) {
              return function(...args: any[]) {
                return func.apply(this, curriedArgs.concat(args));
              }
            }

            function add(...args: number[]) {
              return args.reduce(function(a,b) { return a + b; })
            }
          
MONADS
You think you know monads
YOU DO NOT
PHILIP WADLER

The Three Monad Laws

  1. A monad may not injure a human being or, through inaction, allow a human being to come to harm.
  2. A monad must obey the orders given to it by human beings, except where such orders would conflict with the First Law.
  3. A monad must protect its own existence as long as such protection does not conflict with the First or Second Laws.
KLEISLI TRIPLES

The Elements of Harmony

  1. Applejack
    1. Honesty
  2. Fluttershy
    1. Kindness
  3. Pinkie Pie
    1. Laughter
  4. Rarity
    1. Generosity
  5. Rainbow Dash
    1. Loyalty
  6. Twilight Sparkle
    1. Magic
            function _compose(func1, func2) {
              return function(x: any) {
                return func2(func1(x));
              }
            }
            function compose(...funcs: Function[]) {
              if (funcs.length === 1) return funcs[0];
              if (funcs.length === 2) return function(x: any) {
                return funcs[1](funcs[0](x));
              }
              var tailfunc = funcs.pop();
              return _compose(tailfunc, compose.apply(null, funcs));
            }
          
            function children(node: Element): Element[] {
              var new_list = [], i;
              for (i = 0; i < node.childNodes.length; i++) {
                new_list.push(node.childNodes.item(i));
              }
              return new_list.filter((node) => node instanceof Element)
            }

            var ponies = document.getElementById("ponies");
            children(ponies);
          

Zygohistomorphic prepromorphisms

Used when you really need both semi-mutual recursion and history and to repeatedly apply a natural transformation as you get deeper into the functor. Zygo implements semi-mutual recursion like a zygomorphism. Para gives you access to your result à la paramorphism.

I am Oleg Kiselyov.
I bring greetings from my planet.

Thank you

Bodil Stokke

@bodil

bodil.org/hipster