Skip to content

Instantly share code, notes, and snippets.

@matthieubulte
Created December 26, 2014 23:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthieubulte/dfbfc9436bdce71a02c5 to your computer and use it in GitHub Desktop.
Save matthieubulte/dfbfc9436bdce71a02c5 to your computer and use it in GitHub Desktop.
interface Reducer<a, r> extends Function {
(z : r, x : a) : r;
}
interface Transducer<a, b> extends Function {
<r>(red : Reducer<a, r>) : Reducer<b, r>;
}
interface Unary<a, b> extends Function {
(x:a):b;
}
interface Predicate<a> extends Unary<a, boolean> {
(x:a):boolean;
}
// mapping :: (a -> b) -> Transducer b a
function mapping<a, b>(f : Unary<a, b>):Transducer<b, a> {
return <r>(xf : Reducer<b, r>):Reducer<a, r> => {
return (r:r, x:a):r => {
return xf(r, f(x));
};
};
}
// filtering :: (a -> Bool) -> Transducer a a
function filtering<a>(f: Predicate<a>):Transducer<a, a> {
return <r>(xf: Reducer<a, r>):Reducer<a, r> => {
return (r:r, x:a):r => {
if(f(x)) {
return xf(r, x);
} else {
return r;
}
};
};
}
// flatMapping :: (a -> [b]) -> Transducer b a
function flatMapping<a, b>(f : Unary<a, Array<b>>):Transducer<b, a> {
return <r>(xf : Reducer<b, r>):Reducer<a, r> => {
return (r:r, x:a):r => {
return f(x).reduce(xf, r);
};
};
}
// conj :: Reducer a [a]
function conj<a>(xs:Array<a>, x:a):Array<a> {
return xs.concat([x]);
}
function list<a, b> (xf : Transducer<b, a>):(xs:Array<a>)=>Array<b> {
return (xs:Array<a>):Array<b> => {
return xs.reduce<Array<b>>(xf(conj), []);
};
}
function compose(...fns) {
fns = fns.reverse();
return (init) => {
return fns.reduce((x, f) => f(x), init);
};
}
function even(x:number):boolean {
return x % 2 == 0;
}
function times(x:number):Array<number> {
var ret = [];
for(var i = 0; i<x; i++) {
ret.push(x);
}
return ret;
}
function range(min:number, max:number):Array<number> {
var ret = [];
for(var i = min; i<=max; i++) {
ret.push(i);
}
return ret;
}
var operation = compose(
filtering(even),
flatMapping(times),
mapping((x:number) => Math.pow(2, x))
);
list(operation)(range(1, 10));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment