Created
June 28, 2016 21:30
-
-
Save homam/00353dcbaf9f3d32012b7b9a26b33a22 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 trace = (x, y) => { | |
console.log(x) | |
return y | |
} | |
const trace1 = x => trace(x, x) | |
const id = x => x | |
Promise.prototype.map = function(f) { | |
return this.then(x => { | |
const y = f(x) | |
if(y instanceof Promise) | |
throw 'Expected f :: a -> b but got a -> Promise b' | |
else | |
return y | |
}) | |
} | |
Promise.prototype.bind = function(f) { | |
return this.then(x => { | |
const y = f(x) | |
if(y instanceof Function) | |
throw 'Expected f :: a -> Promise b but got a -> b' | |
if(y instanceof Promise) | |
return y | |
else | |
throw `Expected f :: a -> Promise b but got ${f}` | |
}) | |
} | |
const swap = ([x, y]) => [y, x] | |
const wrap1 = (arrow, before, after, f) => | |
arrow.arr(before).pipe(arrow.arrM(f)).pipe(arrow.arr(after)) | |
const wrap12 = (arrow, before, after, f) => new arrow(x => { | |
let b = arrow.arr(before).run(x) | |
let y = arrow.arrM(id).pipe(arrow.arrM(f)).run(b) | |
return arrow.arrM(id).pipe(arrow.arr(after)).run(y) | |
}) | |
const wrap2 = (arrow, before, after, f) => | |
arrow.arr(before).fanout(arrow.arrM(f)).pipe( | |
arrow.arr(([x, y]) => {after([x, y]); return y })) | |
class Arrow { | |
constructor(T) { | |
// a b c -> a b' c' -> a (b,b') (c,c') | |
this.split = g => this.first().pipe(T.arr(swap)).pipe(g.first()).pipe(T.arr(swap)) | |
// a b c -> a b c' -> a b (c,c') | |
this.fanout = g => T.arr(b => [b, b]).pipe(this.split(g)) | |
} | |
} | |
class Func extends Arrow { | |
constructor(f) { | |
super(Func) | |
this.pipe = g => new Func(x => g.run(this.run(x))) | |
this.map = g => new Func(x => g(this.run(x))) | |
this.bind = g => g(this.run(x)) | |
// a b c -> a (b,d) (c,d) | |
this.first = _ => new Func(([x, y]) => [f(x), y]) | |
this.run = x => f(x) | |
} | |
} | |
Func.id = new Func(x => x) | |
Func.arr = f => new Func(f) | |
Func.arrM = f => new Func(f) | |
//console.log(new Func(x => 2 * x).first().run([2, 33])) | |
//console.log(new Func(x => 2 * x).split(new Func(x => x * 10)).run([2, 33])) | |
//console.log(new Func(x => 2 * x).fanout(new Func(x => x * 10)).run(3)) | |
console.log( | |
wrap12(Func, | |
x => x*2, | |
x => x+1, | |
x => x * x / 2 | |
).run(3) | |
) | |
console.log(wrap2(Func, | |
x => Date.now(), | |
([b, y]) => { | |
console.log(`${y} produced after ${Date.now() - b}`) | |
return "IGNORE IT" | |
}, | |
x => x * 10 | |
).run(3)) | |
class Prom extends Arrow { | |
constructor(f) { | |
super(Prom) | |
this.pipe = g => new Prom(x => this.run(x).bind(y => g.run(y))) | |
this.map = g => new Prom(x => this.run(x).bind(g)) | |
this.bind = g => new Prom(x => this.run(x).bind(g)) | |
this.first = _ => new Prom(([x, y]) => this.run(x).map(x => [x, y])) | |
this.run = x => f(x) | |
} | |
} | |
Prom.id = new Prom(x => Promise.resolve(x)) | |
Prom.arr = f => new Prom(x => Promise.resolve(f(x))) | |
Prom.arrM = f => new Prom(f) | |
wrap12(Prom, | |
x => x*2, | |
x => x+1, | |
x => Promise.resolve(x * x / 2) | |
).run(3) | |
//.map(x => console.log(`P = ${x}`)) | |
wrap2(Prom, | |
x => Date.now(), | |
([b, y]) => { | |
console.log(`${y} produced after ${Date.now() - b}`) | |
return "IGNORE IT" | |
}, | |
x => Promise.resolve(x * x / 2) | |
).run(3) | |
.map(x => console.log(`P = ${x}`)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment