advertisement

Functional Patterns for the non-mathematician

60 %
40 %
advertisement
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.
advertisement

Functional Patterns for the non-mathematician

add(4, 2) //=> 6

// associative add(add(1, 2), 4) == add(1, add(2, 4)) // commutative add(4, 1) == add(1, 4) // identity add(n, 0) == n // distributive multiply(2, add(3,4)) == add(multiply(2, 3), multiply(2, 4))

add(4.4, 2.2) //=> 6.6

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

Add a comment

Related presentations

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

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

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

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

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

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 ...
Read more

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 ...
Read more

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.
Read more

Functional programming patterns for the non-mathematician

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

FUNCTIONAL PATTERNS - YouTube

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

Functional Programming - Roman Zolotarev

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

AvgwKjTPMmM | Machine Learning & Computer Vision Talks

Functional programming patterns for the non-mathematician ' Archive Archive Terms of Service | Privacy Policy. CV Talks Feed. Lecture 25: Computer Vision ...
Read more

Functional Patterns | LinkedIn

View 38 Functional Patterns posts, presentations, experts, and more. Get the professional knowledge you need on LinkedIn.
Read more