awesomely descriptive javascript with monads

79
Awesomely descriptive JavaScript with Monads

Upload: michal-nowak

Post on 19-Jan-2017

210 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Awesomely descriptive JavaScript with monads

Awesomely descriptive JavaScriptwith Monads

Page 2: Awesomely descriptive JavaScript with monads

Theory

Page 3: Awesomely descriptive JavaScript with monads

Monad laws

return a >>= f ≡ f a

m >>= return ≡ m

(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

Page 4: Awesomely descriptive JavaScript with monads

Monad laws

Page 5: Awesomely descriptive JavaScript with monads

Practical theory

Page 6: Awesomely descriptive JavaScript with monads
Page 7: Awesomely descriptive JavaScript with monads

V E G E T A B L EALUE

Page 8: Awesomely descriptive JavaScript with monads
Page 9: Awesomely descriptive JavaScript with monads
Page 10: Awesomely descriptive JavaScript with monads

P => M<S>

f

Page 11: Awesomely descriptive JavaScript with monads

=>

unit

P => M<P>

Page 12: Awesomely descriptive JavaScript with monads

( , ) =>

bind

( M<P> , P => M<S> ) => M<S>

Page 13: Awesomely descriptive JavaScript with monads

( M<P> , P => M<S> ) => M<S>M<P> P => M<S> M<S>

extract value

bind functio

n

m(x)

x

x => m(y) m(y)

bind

Page 14: Awesomely descriptive JavaScript with monads

Monad laws (JavaScript)

bind( unit(v) , f ) ≡ f(v)

bind( monad , unit ) ≡ monad

bind( bind( monad , f ) , g ) ≡

bind( monad, v => bind( f(v) , g ) )

Page 15: Awesomely descriptive JavaScript with monads

monet.js

Page 16: Awesomely descriptive JavaScript with monads

UNIT

Identity(x)Maybe.Some(x)Maybe.None()

Either.Left(e)Either.Right(x)

List(x, Nil)

monad.bind(f)

monad.flatMap(f)

monad.chain(f)

BIND

Page 17: Awesomely descriptive JavaScript with monads

Monad laws (monet.js / Identity)

Identity(v).flatMap(f) ≡ f(v)

id.flatMap(Identity) ≡ id

id.flatMap(f).flatMap( g ) ≡

id.flatMap(v => f(v).flatMap(g))

Page 18: Awesomely descriptive JavaScript with monads

Practice: Identity

Page 19: Awesomely descriptive JavaScript with monads

UNIT

Identity(x)Maybe.Some(x)Maybe.None()

Either.Left(e)Either.Right(x)

List(x, Nil)

monad.bind(f)

monad.flatMap(f)

monad.chain(f)

BIND

Page 20: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper', 'red');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 21: Awesomely descriptive JavaScript with monads
Page 22: Awesomely descriptive JavaScript with monads

const mixInABowl = getBowlOf('pepper') .flatMap(slice) .faltMap(silcedPepper => getBowlOf('tomato') .flatMap(slice) .faltMap(mixedTomato => mix(silcedPepper , mixedTomato)));

Page 23: Awesomely descriptive JavaScript with monads
Page 24: Awesomely descriptive JavaScript with monads

But HOW ?

Page 25: Awesomely descriptive JavaScript with monads

interface Bowl<V> { get(): V;}getBowlOf<V>(name: string): Bowl<V>;slice<S>(vegetable: Vege): Bowl<S>;mix<M>(...ingredients): Bowl<M>;

Page 26: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 27: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 28: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 29: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 30: Awesomely descriptive JavaScript with monads

monet.js

Identity( … )

Page 31: Awesomely descriptive JavaScript with monads

type Op<A, B> = (val:A) => Bowl<B>;

interface Bowl<V> { get(): V; flatMap<S>(f: Op<V, S>): Bowl<S>;}

Page 33: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 34: Awesomely descriptive JavaScript with monads

const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice);

Page 35: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 36: Awesomely descriptive JavaScript with monads

const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice);

const slicedTomatoInABowl = getBowlOf('tomato').flatMap(slice);

Page 37: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 38: Awesomely descriptive JavaScript with monads

const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice);

const mixInABowl = getBowlOf('pepper') .flatMap(slice) .faltMap(silcedPepper => mix(silcedPepper , slicedPepperInABowl.get()));

Page 39: Awesomely descriptive JavaScript with monads

const slicedPepperInABowl = getBowlOf('pepper').flatMap(slice);

const mixInABowl = getBowlOf('pepper') .flatMap(slice) .flatMap(silcedPepper => slicedPepperInABowl .flatMap(mixedTomato => mix(silcedPepper , mixedTomato)));

Page 40: Awesomely descriptive JavaScript with monads

const mixInABowl = getBowlOf('pepper') .flatMap(slice) .faltMap(silcedPepper => getBowlOf('tomato') .flatMap(slice) .flatMap(mixedTomato => mix(silcedPepper , mixedTomato)));

Page 41: Awesomely descriptive JavaScript with monads

var pepperInABowl = getBowlOf('pepper', 'red');var pepper = pepperInABowl.get();var slicedPepperInABowl = slice(pepper);var tomatoInABowl = getBowlOf('tomato');var tomato = tomatoInABowl.get();var slicedTomatoInABowl = slice(tomato);var slicedPepper = slicedPepperInABowl.get();var slicedTomato = slicedTomatoInABowl.get();var mixInABowl = mix(slicedPepper, slicedTomato);

Page 42: Awesomely descriptive JavaScript with monads

Practice: Maybe

Page 43: Awesomely descriptive JavaScript with monads

UNIT

Identity(x)Maybe.Some(x)Maybe.None()

Either.Left(e)Either.Right(x)

List(x, Nil)

monad.bind(f)

monad.flatMap(f)

monad.chain(f)

BIND

Page 44: Awesomely descriptive JavaScript with monads
Page 45: Awesomely descriptive JavaScript with monads

let spiceMix;

const salt = getSpice('salt');

let coriander = getSpice('coriander');

if (coriander) {

coriander = crush(coriander);

}

if (coriander && salt && isPowdered(salt)) {

spiceMix = mixSpice(salt , coriander);

}

spiceMix = vegeta;

Page 46: Awesomely descriptive JavaScript with monads

let spiceMix;

const salt = getSpice('salt');

let coriander = getSpice('coriander');

if (coriander) {

coriander = crush(coriander);

}

if (coriander && salt && isPowdered(salt)) {

spiceMix = mixSpice(salt , coriander);

}

spiceMix = vegeta;

Page 47: Awesomely descriptive JavaScript with monads

const spiceMix = getSpice('salt').filter(isPowdered)

.flatMap(salt =>

getSpice('coriander').map(crush)

.flatMap(coriander =>

mixSpice(salt , coriadner)))

.orJust(vegeta);

Page 48: Awesomely descriptive JavaScript with monads

But HOW ?

Page 49: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V>;

crush(spice: S): S;

isPowdered(spice: S): boolean;

Page 50: Awesomely descriptive JavaScript with monads
Page 51: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V>;

crush(spice: S): S;

isPowdered(spice: S): boolean;

Page 52: Awesomely descriptive JavaScript with monads
Page 53: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V>;

crush(spice: S): S;

isPowdered(spice: S): boolean;

Page 54: Awesomely descriptive JavaScript with monads

monet.js

Maybe

Page 55: Awesomely descriptive JavaScript with monads

interface Maybe<T> {

flatMap<V>(fn: (val: T) => Maybe<V>):

Maybe<V>;

map<V>(fn: (val: T) => V): Maybe<V>;

filter(fn: (val: T) => boolean): Maybe<T>;

orJust(val: T): T;

}

Page 56: Awesomely descriptive JavaScript with monads

const silkySalt = getSpice('salt').filter(isPowdered);

const crushedCoriander = getSpice('coriander').map(crush);

const spiceMixMaybe = silkySalt.flatMap(salt =>

crushedCoriander.flatMap(coriander =>

mixSpice( salt , coriadner )));

const spiceMix = spiceMixMaybe.orJust(vegeta);

Page 57: Awesomely descriptive JavaScript with monads

const crushedCoriander = getSpice('coriander').map(crush);

const spiceMixMaybe =

getSpice('salt').filter(isPowdered).flatMap(salt =>

crushedCoriander.flatMap(coriander =>

mixSpice( salt , coriadner )));

const spiceMix = spiceMixMaybe.orJust(vegeta);

Page 58: Awesomely descriptive JavaScript with monads

const spiceMixMaybe =

getSpice('salt').filter(isPowdered).flatMap(salt =>

getSpice('coriander').map(crush).flatMap(coriander =>

mixSpice( salt , coriadner )));

const spiceMix = spiceMixMaybe.orJust(vegeta);

Page 59: Awesomely descriptive JavaScript with monads

const spiceMixMaybe = getSpice('salt').filter(isPowdered)

.flatMap(salt =>

getSpice('coriander').map(crush)

.flatMap(coriander =>

mixSpice( salt , coriadner )));

const spiceMix = spiceMixMaybe.orJust(vegeta);

Page 60: Awesomely descriptive JavaScript with monads

const spiceMix = getSpice('salt').filter(isPowdered)

.flatMap(salt =>

getSpice('coriander').map(crush)

.flatMap(coriander =>

mixSpice( salt , coriadner )));

.orJust(vegeta)

Page 61: Awesomely descriptive JavaScript with monads

const spiceMix = getSpice('salt')

.filter(isPowdered)

.flatMap(salt =>

getSpice('coriander')

.map(crush)

.flatMap(coriander =>

mixSpice(salt , coriadner)))

.orJust(vegeta);

Page 62: Awesomely descriptive JavaScript with monads

null

Page 63: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V> { let spice = locker.get(name); if (spice != null) { return Some(spice); } return None();}

Page 64: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return Some(spice); } return None();}

Page 65: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return … ? } return None();}

Page 66: Awesomely descriptive JavaScript with monads

monet.js

Some( … )

Page 67: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return Some(spice); } return None();}

Page 68: Awesomely descriptive JavaScript with monads

monet.js

None()

Page 69: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V> { const spice = locker.get(name); if (spice != null) { return Some(spice); } return None();}

Page 70: Awesomely descriptive JavaScript with monads

monet.js

.fromNull()

Page 71: Awesomely descriptive JavaScript with monads

getSpice<V>(name: string): Maybe<V> {

return Maybe.fromNull( locker.get(name) );

}

Page 72: Awesomely descriptive JavaScript with monads
Page 73: Awesomely descriptive JavaScript with monads

goo.gl/cvGVeo

Page 74: Awesomely descriptive JavaScript with monads

const saladBowl = mixInABowl

.flatMap(mixedVegetables =>

mix(mixedVegetables, spiceMix));

Page 75: Awesomely descriptive JavaScript with monads

e a t i t

Page 76: Awesomely descriptive JavaScript with monads

Monads

IdentityMaybeEither

ValidationListNEL

ReaderFreeIO

?

Page 77: Awesomely descriptive JavaScript with monads

Monads

IdentityMaybeEither

ValidationListNEL

ReaderFreeIO

Promise

Page 78: Awesomely descriptive JavaScript with monads

T H X

Page 79: Awesomely descriptive JavaScript with monads

Jakub . Strojewski @gmail.com

u l f r y k