Skip to content

Instantly share code, notes, and snippets.

/unionBy.js Secret

Created September 8, 2016 17:35
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 anonymous/b94c96cbb78fe9966e93964d7cb34e9e to your computer and use it in GitHub Desktop.
Save anonymous/b94c96cbb78fe9966e93964d7cb34e9e to your computer and use it in GitHub Desktop.
const unionBy = p => xs => ys => {
// this scope has knowledge that a Set is used
// don't leak knowledge of Set leak into user-supplied predicate
let s = createSet(xs);
// this line is left expanded for clarity
// let zs = filter (y => p (z => s.has(z) ? false : s.add(z)) (y)) (ys)
// it eta reduces to
let zs = filter (p (z => s.has(z) ? false : s.add(z))) (ys);
return concat(xs) (afrom (zs));
};
// then union and unionCI change like this
// see? no knowledge that a Set was used ^_^
const union = unionBy (apply);
const unionCI = unionBy (p=> x=> p(x.toLowerCase()));
// you will probably want this then too
const unionByAll = p => (xs,...xxs) => {
return foldl (unionBy (p)) (xs) (xxs);
};
@ivenmarquardt
Copy link

ivenmarquardt commented Sep 8, 2016

The original function was concat_(xs) (filter(notf(has(zs))) (ys)), which I converted into concat_(xs) (filter(pred(zs)) (ys)), which was a bad idea. To separate it in two lines is good regarding readability. I'll edit SO tomorrow. And I really forgot the let zs declaration - brain damage. Thanks Naomi.

@ivenmarquardt
Copy link

I fully grasped your solution finally. The magic is in the interaction between unionBy and p. I love it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment