# Functional Patterns for the non-mathematician

57 %
43 %
Information about Functional Patterns for the non-mathematician
Technology

Published on March 15, 2014

Author: drboolean

Source: slideshare.net

## Description

Fluentconf 2014 talk:

Functional design patterns such as lenses, arrows, functors, and monads all come from category theory. To fully grok them, you’ll probably have to wade through the whitest white papers, fighting the mathematical syntax and abstract examples.

I’m hoping to demonstrate the ideas into javascript. I’ll be showing direct and practical applications for every day programming.

Functional Patterns for the non-mathematician

var inc = new Increaser(4); inc.increaseBy(2); inc.value(); // 6

Interfaces Properties/Laws Polymorphic Composable

Currying

var reverseCap = compose(capitalize, reverse) reverseCap(“hello”) //=> “Olleh” Composition

var reverseCap = compose(capitalize, reverse) reverseCap(“hello”) //=> “Olleh” Composition

var reverseCap = compose(capitalize, reverse)(“hello”) //=> “Olleh” Composition “hello”“olleh”“Olleh”

compose(compose(f, g), h) == compose(f, compose(g, h)) Composition (associativity)

compose(f, g, h) Composition (associativity)

var i = compose(g, h) compose(f, i) Composition (associativity)

var getFromDb = compose(pluck('rows'), User.findAll) var cleanUpData = compose(capitalize, pluck('name')) var renderTemplate = TemplateEngine.render(‘users_table') var makePage = compose(renderTemplate, map(cleanUpData), getFromDb) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20})

var getFromDb = compose(pluck('rows'), User.findAll) var cleanUpData = compose(capitalize, pluck('name')) var renderTemplate = TemplateEngine.render(‘users_table') var makePage = compose(renderTemplate, map(cleanUpData), getFromDb) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) makePage({limit: 20}) Perfect world

function (property, x) { return x[property]; } Getters/Setters function (property, value, x) { x[property] = value; return x; }

Lenses over(l, f, x) view(l, x) set(l, y, x)

var user = {id: 1, name: ‘Alicia'} var L = makeLenses([‘name’]) view(L.name, user) // 'Alicia' set(L.name, 'Ally', user) // {id: 1, name: 'Ally'} over(L.name, toUpperCase, user) // {id: 1, name: 'ALICIA'} Lenses

var user = {id: 1, name: {first: ‘doris’, last: ‘day’ }} var L = makeLenses([‘name’, ‘first’]) var firstNameChar = compose(L.name, L.first, _1) over(firstNameChar, toUpperCase, user) //=> {id: 1, name: {first: ‘Doris’, last: ‘day’ }} Lenses

view(l, set(l, b, a)) == b set(l, view(l, a), a) == a set(l, c, set(l, b, a)) == set(l, c, a) Lens laws

if(x !== null && x !== undefined) { return f(x) } Null checking

fmap(f, Maybe(x)) Null checking

var fmap = function(f, mappable) { return mappable.map(f) } Null checking

fmap(function(x) { return x.toUpperCase() }, Maybe(‘hi’)) //=> Maybe(‘HI’) fmap(function(x) { return toUpperCase(x); }, Maybe(null)) //=> Maybe(null) Null checking

fmap(function(x) { return x.toUpperCase() }, Maybe(‘hi’)) //=> Maybe(‘HI’) fmap(function(x) { return x.toUpperCase() }, Maybe(null)) //=> Maybe(null) Null checking

compose(fmap(f), Maybe) Null checking

var id = function(x) { return x; } fmap(id, x) == id(x) Fmap laws (identity)

compose(fmap(f), fmap(g)) == fmap(compose(f, g)) Fmap laws (composition)

if(x !== null && x !== undefined) { return f(x) } else { throw ‘Some Error!’ } Error Handling

Error Handling fmap(f, Either(‘Some error’, x))

Either(‘need an int’, 3) //=> Right(3) fmap(function(x) { return x + 1; }, Either(‘need an int’, undefined)) //=> Left(‘need an int’) Error Handling

Either(‘need an int’, 3) //=> Right(3) Either(‘need an int’, undefined)) //=> Left(‘need an int’) Error Handling

fmap(function(x) { return x + 1; }, Right(2)) //=> Right(3) fmap(function(x) { return x + 1; }, Either(‘need an int’, undefined)) //=> Left(‘need an int’) Error Handling

fmap(function(x) { return x + 1; }, Right(2)) //=> Right(3) fmap(function(x) { return x + 1; }, Left(‘need an int’)) //=> Left(‘need an int’) Error Handling

compose(fmap(f), Either(‘error’)) Error Handling

f(x, function(y) { return g(y); }); Future values

Future values fmap(f, Promise(x))

var p = new Promise(); fmap(function(x) { return log(reverse(x)) }, p) //=> Promise() p.resolve([1,2,3]) //=>[3, 2, 1] Future values

Something that implements map Functor

if(x !== null && x !== undefined) { var y = f(x) if(y !== null && y !== undefined) { return g(y) } } Nesting

f(x, function(y) { return g(y, function(z) { return h(z) }) }) Nesting

compose(mjoin, fmap(f)) Nesting

var getField = compose(Maybe, document.querySelector) var getValue = compose(Maybe, pluck(‘value’)) var greet = compose(fmap(fmap(concat(‘hello’))), fmap(getValue), getField) greet(‘#name’) //=> Maybe(Maybe(‘hello chris’)) var greet = compose(fmap(concat(‘hello’)), mjoin, fmap(getValue), getField) greet(‘#name’) //=> Maybe(‘hello chris’) Nesting

var getField = compose(Maybe, document.querySelector) var getValue = compose(Maybe, pluck(‘value’)) var greet = compose(fmap(fmap(concat(‘hello’))), fmap(getValue), getField) greet(‘#name’) //=> Maybe(Maybe(‘hello chris’)) var greet = compose(fmap(concat(‘hello’)), mjoin, fmap(getValue), getField) greet(‘#name’) //=> Maybe(‘hello chris’) Nesting

compose(mjoin, fmap(g), mjoin, fmap(f)) Nesting mcompose(g, f)

compose(mjoin, fmap(g), mjoin, fmap(f)) Nesting mcompose(g, f)

mcompose(mcompose(f, g), h) == mcompose(f, mcompose(g, h)) mcompose(f, M) == f mcompose(M, f) == f Monad laws

Multiple null args var notNull = function(x) { return x !== null && x !== undefined } if(notNull(x) && notNull(y)) { return f(x, y) }

Multiple Async fn’s var y,z; f(x, function(result) { y = result; if(z) { return h(y, z) }) }) g(x, function(result) { z = result; if(y) { return h(y, z) }) })

liftA2(f, A(x), A(y)) Multiple values

liftA3(f, A(x), A(y), A(z)) Multiple values

liftA2(add, Maybe(3), Maybe(4)) //=> Maybe(7) liftA2(add, Maybe(null), Maybe(4)) //=> Maybe(null) Multiple values

liftA2(add, Maybe(3), Maybe(4)) //=> Maybe(7) liftA2(add, Maybe(null), Maybe(4)) //=> Maybe(null) Multiple values

var tweets_p = Http.get(‘/twitter/tweets’) var photos_p = Http.get(‘/flickr/photos’) var makeCollage = _.curry(function (tweets, photos){}) liftA2(makeCollage, tweets_p, photos_p) Multiple values

// identity ap(A(id), m) == m // composition ap(ap(ap(A(compose), f), g), w) == ap(f, ap(g, w)) // homomorphism ap(A(f), A(x)) == A(f(x)) // interchange ap(u, A(x)) == ap(A(function(f) { return f(x); }), u) Applicative laws

Accumulation reduce(function(acc, x) { return acc + x; }, 0, [1,2,3])

Accumulation reduce(function(acc, x) { return acc * x; }, 1, [1,2,3])

Accumulation reduce(function(acc, x) { return acc || x; }, false, [false, false, true])

Accumulation reduce(function(acc, x) { return acc && x; }, true, [false, false, true])

Accumulation reduce(function(acc, x) { return acc > x ? acc : x; }, 0, [12, 5, 35])

Monoid mappend(m, m) mempty(m) mconcat([m])

Monoid mappend(m, m) mempty(m) mconcat([m])

mconcat([Sum(1), Sum(2), Sum(3)]) //=> Sum(6) Accumulation

mconcat([Product(1), Product(2), Product(3)]) //=> Product(6) Accumulation

mconcat([Max(13), Max(2), Max(9)]) //=> Max(13) Accumulation

mconcat([Any(false), Any(false), Any(true)]) //=> Any(true) Accumulation

mconcat([All(false), All(false), All(true)]) //=> All(false) Accumulation

compose(mconcat, map(M)) Accumulation

// left identity mappend(mempty, x) == x // right identity mappend(x, mempty) == x // associativity mappend(mappend(x, y), z) == mappend(x, mappend(y, z)) Monoid laws

Combinators function(x) { return [f(x), g(x)] }

Combinators function(x, y) { return [f(x), g(y)] }

compose(f, g) ampersand(f, g) asterisk(f, g) first(f) second(f) Arrows

first(reverse)([‘Stan’, ‘Lee']) // [‘natS’, ‘Lee’] second(reverse)([‘Stan’, ‘Lee']) // [‘Stan’, ‘eeL’] ampersand(reverse, toUpperCase)(‘Stan’) // [‘natS’, ‘STAN’] asterisk(reverse, toUpperCase)([‘Stan’, ‘Lee']) // [‘natS’, ‘LEE’] Arrows

A(id) == id A(compose(f, g)) == A(compose(f, A(g))) first(A(f)) == A(first(f)) first(compose(f, g)) == compose(first(f), first(g)) compose(first(f), A(pluck(0))) == compose(A(pluck(0)), f) compose(first(f), A(asterisk(id, g)) == compose(A(asterisk(id, g)), first(f)) compose(first(first(f)), A(assoc) == compose(A(assoc), first(f)) Arrow laws

Thanks! @drboolean https://github.com/DrBoolean/patterns_talk

 User name: Comment:

## Related presentations

#### Neuquén y el Gobierno Abierto

October 30, 2014

Presentación que realice en el Evento Nacional de Gobierno Abierto, realizado los ...

#### Decision CAMP 2014 - Erik Marutian - Using rules-b...

October 16, 2014

In this presentation we will describe our experience developing with a highly dyna...

#### Schema.org: What It Means For You and Your Library

November 7, 2014

Presentation to the LITA Forum 7th November 2014 Albuquerque, NM

#### WearableTech: Una transformación social de los p...

November 3, 2014

Un recorrido por los cambios que nos generará el wearabletech en el futuro

#### O Impacto de Wearable Computers na vida das pessoa...

November 5, 2014

Um paralelo entre as novidades & mercado em Wearable Computing e Tecnologias Assis...

#### All you need to know about the Microsoft Band

November 6, 2014

Microsoft finally joins the smartwatch and fitness tracker game by introducing the...

## Related pages

### Functional programming patterns for the non-mathematician ...

I hit on some practical use cases for functors/applicatives/monads. Pretty fast and quick run through of everything, but you can't learn the ...

### Functional Programming Patterns for the Non-Mathematician ...

Functional Programming Patterns for the Non-Mathematician - Brian Lonsdorf by O'Reilly Media, Inc. Abstractions in FP can be daunting if you're not ...

### Functional Programming Patterns for the Non-Mathematician ...

Brian Lonsdorf is CTO of looprecur, the CTO of looprecur. He speaks of programming functionally frequently at conferences and meetups around the bay area.

### Functional programming patterns for the non-mathematician

Machine Learning & Computer Vision Talks Lectures, Keynotes, Panel Discussions…. Lectures; Talks; KeyNotes; Discussions; Tutorials; Misc; Programming ...

Functional programming patterns for the non-mathematician (cut) ... the Problem, Remember the Pattern ... Functional Patterns 1,976 ...

### Functional Programming - Roman Zolotarev

If you have no experience with functional programming yet please read ... patterns for the non-mathematician by ... cd functional-program ...