Created
March 10, 2011 10:44
-
-
Save poetix/863932 to your computer and use it in GitHub Desktop.
Javascript Combinator examples
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
"use strict"; | |
// compose :: (b -> c) -> (a -> b) -> (a -> c) | |
function compose(g, f) { | |
return function() { | |
return g(f.apply(f, arguments)); | |
}; | |
} | |
// each :: [a] -> (a -> _) -> _ | |
function each(xs, f) { | |
var i; | |
for (i = 0; i < xs.length; ++i) { | |
f(xs[i], i); | |
} | |
} | |
// map :: [a] -> (a -> b) -> [b] | |
function map(f, xs) { | |
var i, result = []; | |
each(xs, function(x, i) { | |
result[i] = f(x); | |
}); | |
return result; | |
} | |
// concatMap :: [a] -> (a -> [b]) -> [b] | |
function concatMap(f, xs) { | |
var k=0, result = []; | |
each(xs, function(x) { | |
each(f(x), function(y) { | |
result[k] = y; | |
k += 1; | |
}); | |
}); | |
return result; | |
} | |
// listCompose :: (b -> [c]) -> (a -> [b]) -> (a -> [c]) | |
function listCompose(g, f) { | |
return function() { | |
return concatMap(g, f.apply(f, arguments)); | |
}; | |
} | |
// foldr :: (a -> b) -> b -> [a] -> [b] | |
function foldr(f, a, xs) { | |
return foldr_(f, a, xs, xs.length - 1); | |
} | |
function foldr_(f, a, xs, i) { | |
var x = xs[i]; | |
a = f(x, a); | |
if (i === 0) { return a; } | |
return foldr_(f, a, xs, i - 1); | |
} | |
// foldl :: (a -> b) -> b -> [a] -> [b] | |
function foldl(f, a, xs) { | |
return foldl_(f, a, xs, 0); | |
} | |
function foldl_(f, a, xs, i) { | |
var x = xs[i] | |
a = f(x, a); | |
if (i === xs.length - 1) { return a; } | |
return foldl_(f, a, xs, i + 1); | |
} | |
// makePipe :: ((b -> c) -> (a -> b) -> (a -> c)) -> [(* -> *)] -> (* -> *) | |
function makePipe(compositor) { | |
return function() { | |
var args = Array.prototype.slice.call(arguments), | |
first = args.shift(); | |
return foldl(compositor, first, args); | |
}; | |
} | |
var pipe = makePipe(compose); | |
var listPipe = makePipe(listCompose); | |
function add(rhs) { | |
return function(lhs) { | |
return lhs + rhs; | |
}; | |
} | |
function subtract(rhs) { | |
return function(lhs) { | |
return lhs - rhs; | |
}; | |
} | |
function multiply(rhs) { | |
return function(lhs) { | |
return lhs * rhs; | |
}; | |
} | |
var calc = pipe( | |
add(5), | |
multiply(7), | |
subtract(4) | |
); | |
print(calc(8)); | |
function sum(seq) { | |
return foldr(function(a, b) { return a + b; }, 0, seq); | |
} | |
function avg(seq) { | |
return sum(seq) / seq.length; | |
} | |
var tryAll = listPipe( | |
function(a) { | |
return [a, a + 1, a - 1]; | |
}, | |
function(b) { | |
return [b, b * 2.0, b / 2.0]; | |
}, | |
function(c) { | |
return [c, c + 1, c - 1]; | |
} | |
); | |
var getResult = pipe( | |
tryAll, | |
avg, | |
print); | |
getResult(10); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment