What every hipster should know about Functional Programming @bodil

The Great Paradigms

Stand back! We know regular expressions. We know regular expressions.

What's the problem? A monad is just a monoid in the category of endofunctors.

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!"; } Discover that hello is a variable. Reassign: ohai = hello; Create the invoke function.

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) { ... } Reduce ponies. Reduce numbers.

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; } Map is a special case of reduce. Reduce ponies with shoutyMapReducer. Map ponies with CAPS. They're identical!

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()]); } Higher order function! Run it with CAPS. Reduce ponies using mapReducer. Implement map using reduce and mapReducer.

COMBINATORS

function square(x: number) { return x * x; } Show square(8). Show andThree(square). Show andThree(square)(8).

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 + "!"; } Run CAPS(hi(s)). Write compose func then compose hi and CAPS. Then compose CAPS and hi.

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 DO NOT You think you know monads

PHILIP WADLER

The Three Monad Laws A monad may not injure a human being or, through inaction, allow a human being to come to harm. A monad must obey the orders given to it by human beings, except where such orders would conflict with the First Law. 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 Applejack Honesty Fluttershy Kindness Pinkie Pie Laughter Rarity Generosity Rainbow Dash Loyalty Twilight Sparkle 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.