Created
October 7, 2016 07:22
-
-
Save abuseofnotation/a05b5d8ab697ee893f35e9ee5f52770e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { adt, object } = require('./core') | |
const Free = adt.data('Free', { | |
Pure: (value) => ( { value } ), | |
Impure: (value, func) => ( { value, func } ) | |
}).derive(adt.show) | |
const { Pure, Impure } = Free | |
Pure.prototype.chain = function (f) { | |
return f(this.value) | |
} | |
Impure.prototype.chain = function (f) { | |
return Impure(this.value, (value) => this.func(value).chain(f)) | |
} | |
Free.map = function (f) { | |
return this.chain((val) => Free.of(f(val))) | |
} | |
Free.fold = function (interpret = (a) => a) { | |
return this.cata({ | |
Pure: ({ value }) => value, | |
Impure: ({ value, func }) => func(interpret(value)) | |
.fold(interpret) | |
}) | |
} | |
Free.of = Pure | |
Free.lift = (value) => Impure(value, a => a) | |
const makeFree = (constructor) => (...args) => Free.lift(constructor(...args)) | |
const adtFree = (variants) => { | |
return object.mapValues(variants, makeFree) | |
} | |
const ST = adt.data('ST', { | |
get: (key) => ({ key }), | |
set: (key, val) => ({ key, val}) | |
}).derive(adt.show) | |
const freeST = adtFree(ST) | |
const IO = adt.data('IO', { | |
print: (value) => ({ value }) | |
}).derive(adt.show) | |
const freeIO = adtFree(IO) | |
const saveAndLoad = (value) => | |
Free.of(value) | |
.chain((val) => freeST.set('myVal', val)) | |
.map((val) => val * 2) | |
.chain((valDoubled) => | |
freeST.get('myVal') | |
.chain((originalVal) => | |
freeIO.print(`original=${originalVal}, transformed=${valDoubled} `))) | |
const state = {} | |
const foldFree = (val) => { | |
if(ST.hasInstance(val)) { | |
console.log('st') | |
return val.cata({ | |
set({key, val}) { | |
state[key] = val; | |
return Pure(val) | |
}, | |
get({key}) { | |
return Pure(state[key]) | |
} | |
}) | |
} else if (IO.hasInstance(val)) { | |
console.log('io') | |
return val.cata({ | |
print({value}) { | |
console.log(value) | |
return Pure(value) | |
} | |
}) | |
} else { | |
console.log('error', val) | |
} | |
} | |
const result = saveAndLoad(33).fold(foldFree) | |
const { cont } = adt.data('continuation', { | |
cont(cont) { | |
return { cont } | |
} | |
}) | |
cont.prototype.chain = function (f) { | |
return cont((run) => { | |
debugger | |
this.cont(f).run(run) | |
}) | |
} | |
cont.of = function (val) { | |
return cont((f) => f(val)) | |
} | |
cont.prototype.run = function(callback = a => console.log(a)) { | |
this.cont(callback) | |
} | |
inc = (val) => (cb) => { console.log(val); setTimeout(() => { console.log(val); cb(val + 1)} , 10)} | |
inc(1)((a) => console.log(a)) | |
c1 = cont.of(1) | |
c2 = c1.chain((val) => cont(inc(val))).run() | |
c3 = c2.chain((val) => cont(inc(val))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment