Skip to content

Instantly share code, notes, and snippets.

@mvaldesdeleon
Last active November 29, 2017 17:09
Show Gist options
  • Save mvaldesdeleon/f8a84d9e777437d84c0036c9c903f445 to your computer and use it in GitHub Desktop.
Save mvaldesdeleon/f8a84d9e777437d84c0036c9c903f445 to your computer and use it in GitHub Desktop.
Transducers
const reduce = reducer => z => as => as.reduce((z, a) => reducer(z)(a), z);
// reducer :: (z -> a -> z)
// transducer :: (z -> a -> z) -> (z -> b -> z)
// contramapT :: (b -> a) -> (z -> a -> z) -> (z -> b -> z)
const contramapT = fn => reducer => (z => b => reducer(z)(fn(b)));
// filterT :: (a -> Bool) -> (z -> a -> z) -> (z -> a -> z)
const filterT = pr => reducer => (z => a => pr(a) ? reducer(z)(a) : z);
// takeT :: Int -> (z -> a -> z) -> (z -> a -> z)
const takeT = n => reducer => (c => (z => a => c-- > 0? reducer(z)(a) : z))(n);
const C = (...fns) => fns.reduceRight((cfn, fn) => x => cfn(fn(x)), x => x);
const cons = as => a => ([...as, a]);
const triple = contramapT(x => x * 3);
const odds = filterT(x => x % 2);
const takeTwo = takeT(2);
const transduce = transducer => base => z => as => reduce(transducer(base))(z)(as);
transduce(C(takeTwo, odds, triple))(cons)([])([1,2,3,4,5,6,7,8,9,10]);
// [3, 9]
const sum = z => a => z + a;
transduce(C(takeTwo, odds, triple))(sum)(0)([1,2,3,4,5,6,7,8,9,10]);
// 12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment