Skip to content

Instantly share code, notes, and snippets.

@xgrommx
Forked from Avaq/fold.js
Created July 23, 2016 01:02
Show Gist options
  • Save xgrommx/440b0642fde08a445261dcd96e381140 to your computer and use it in GitHub Desktop.
Save xgrommx/440b0642fde08a445261dcd96e381140 to your computer and use it in GitHub Desktop.
Functional JavaScript cookbook
//Combinators
const I = x => x;
//List manipulation
const head = xs => xs[0];
const tail = xs => xs.slice(1);
const append = x => xs => [...xs, x];
//Iteration
const foldl = f => y => xs => xs.length > 0 ? foldl(f)(f(y)(head(xs)))(tail(xs)) : y;
const foldr = f => y => xs => xs.length > 0 ? f(foldr(f)(y)(tail(xs)))(head(xs)) : y;
const map = f => foldl(y => x => append(f(x))(y))([]);
const filter = f => foldl(y => x => f(x) ? append(x)(y) : y)([]);
//Function composition
const compose = f => g => x => f(g(x));
const pipe = foldr(compose)(I);
//Math
const add = a => b => a + b;
const mult = a => b => a * b;
const gt = a => b => b > a;
//Program
pipe([
map(add(1)),
map(mult(2)),
filter(gt(10))
])
([1, 2, 3, 4, 5, 6, 7, 8]);
//Setup
console.clear();
const randDelay = () => Math.round(Math.random() * 500) + 100;
const randBool = () => !! Math.round(Math.random());
const {repeat, curry, compose, tap, sequence, chain} = R;
const slowFuture = Future((f, g) => setTimeout(compose(randBool() ? f : g, tap(() => console.log('asd'))), randDelay(), 'hello'));
const lotsafutures = repeat(slowFuture, 11);
//parallelize :: Number -> [Chain x] -> Chain [x]
const parallelize = curry((i, xs) => {
const next = x => i < xs.length ? attach(xs[i++]) : Future.of(x);
const attach = m => m.chainReject(() => Future.of(null)).chain(next);
return sequence(Future.of, xs.slice(0, i).map(attach));
});
//Execute
parallelize(3, lotsafutures).fork(console.log, console.log)
const permutations = R.compose(R.sequence(R.of), R.flip(R.repeat));
permutations(2, [1,2,3])
console.clear();
const then = Date.now();
const log = x => console.log(`${Date.now() - then} - ${x}`);
const err = x => console.log(`${Date.now() - then} - ERROR: ${x}`);
const {K, I, pipe} = S;
const {curry, reduce, ap, once, compose, chain, map} = R;
const ftap = f => a => f(a).map(K(a));
//A mock database
const connect = curry(config => Future.cache(Future((rej, res) => (log('Connecting...'), res({name: 'Connection', config})))))
const close = curry(connection => Future((rej, res) => (log(`Closed ${connection.name}`), res(null))))
const query = curry((x, connection) => Future((rej, res) =>
setTimeout(() => (log(`QUERY[${connection.name}][${x}]`), res(eval(x))), 300)
));
const RFuture = Reader.T(Future);
const closeConnection = () => RFuture.ask.chain(pipe([chain(close), RFuture.lift]));
const querySquare = n => RFuture.ask.chain(pipe([chain(query(`${n} * ${n}`)), RFuture.lift]));
RFuture(chain(query('1 + 1')))
.chain(querySquare)
.chain(ftap(closeConnection))
.run(connect({foo: 'bar'}))
.fork(err, log)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment