Jon's Programming Blog

Notes On Functional Programming

Patterns for the Non-Mathematician with Brian Lonsdorf

Patterns for the Non-Mathematician with Brian Lonsdorf

Lenses

Using lenses for composable/polymorphic model manipulation.

E.g.,

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'}}

Maybe

Use Maybe (Haskell) types (Option types in bilby.js / Scala style) to make composition easier. This works with fmap (functor maps). Returns resultant option.

Error Handling (Either)

Either('need an int', 3)
//=> Right(3)

Either('need an int', undefined)
//=> Left('need an int')

fmap(function(x){return x+1;}, Right(2))
//=> Right(3)

fmap(function(x){return x+1;}, Left('need an int'))
//=> Left('need an int')

compose(fmap(f), Either(error))

Future Values

I’ll have to come back to this one later when I use it more.

Functor

Something that implements map

Like Promise, Maybe, Either, etc.

Nesting

Use mjoin (flatMap – bilby.js) to flatten 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')

Mutiple Values (liftA2)

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

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

liftA2(add, Maybe(null), Maybe(4))
//=> Maybe(null)

Examples

Lenses

var L = makeLenses(['body', 'viewed'])
var comment = {id:2, body: "this is a *great* post", viewed: false}
var showOnScreen = log
var prog = compose(showOnScreen, set(L.viewed, true), over(L.body, markdown))
prog(comment)
//=> {id:2, body: '<p>this is a <em>great</em> post!</p>', viewed: true}

Either/Maybe

var getWords = compose(Either('you need some words')
               , match(/\w+/g))
var showCount = compose(concat('The count is: ')
                , pluck('length'))
var prog = compose(fmap(showCount), getWords)
var result = progr(' blah ')
log(result)
//=> Right('The count is: 1')

These notes came from the video below:

The full slides are also available.

bilby.js & functional programming Spreadsheet Budget Launched