Skip to content

Instantly share code, notes, and snippets.

@abuseofnotation
Created October 7, 2016 07:22
Show Gist options
  • Save abuseofnotation/a05b5d8ab697ee893f35e9ee5f52770e to your computer and use it in GitHub Desktop.
Save abuseofnotation/a05b5d8ab697ee893f35e9ee5f52770e to your computer and use it in GitHub Desktop.
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