Created
December 26, 2014 23:48
-
-
Save matthieubulte/dfbfc9436bdce71a02c5 to your computer and use it in GitHub Desktop.
This file contains 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
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