Skip to content

Instantly share code, notes, and snippets.

@Avaq
Last active April 24, 2023 22:31
Embed
What would you like to do?
Common combinators in JavaScript
const I = x => x
const K = x => y => x
const A = f => x => f (x)
const T = x => f => f (x)
const W = f => x => f (x) (x)
const C = f => y => x => f (x) (y)
const B = f => g => x => f (g (x))
const S = f => g => x => f (x) (g (x))
const S_ = f => g => x => f (g (x)) (x)
const S2 = f => g => h => x => f (g (x)) (h (x))
const P = f => g => x => y => f (g (x)) (g (y))
const Y = f => (g => g (g)) (g => f (x => g (g) (x)))
Name # Haskell Ramda Sanctuary Signature
identity I id identity I a → a
constant K const always K a → b → a
apply A ($) call I¹ (a → b) → a → b
thrush T (&) applyTo T a → (a → b) → b
duplication W join² unnest² join² (a → a → b) → a → b
flip C flip flip flip (a → b → c) → b → a → c
compose B (.), fmap² map² compose, map² (b → c) → (a → b) → a → c
substitution S (<*>)² ap² ap² (a → b → c) → (a → b) → a → c
chain S_³ (=<<)² chain² chain² (a → b → c) → (b → a) → b → c
converge S2³ apply2way, liftA2², liftM2² lift2² (b → c → d) → (a → b) → (a → c) → a → d
psi P on on on (b → b → c) → (a → b) → a → a → c
fix-point4 Y fix (a → a) → a

¹) The A-combinator can be implemented as an alias of the I-combinator. Its implementation in Haskell exists because the infix nature gives it some utility. Its implementation in Ramda exists because it is overloaded with additional functionality.

²) Algebras like ap have different implementations for different types. They work like Function combinators only for Function inputs.

³) I could not find a consistent name for these combinators, but they are common enough in the JavaScript ecosystem to justify their inclusion. I named them myself in order to refer to their implementation.

4) In JavaScript and other non-lazy languages, it is impossible to implement the Y-combinator. Instead a variant known as the applicative or strict fix-point combinator is implemented. This variant is sometimes rererred to as the Z-combinator. The implementation found in combinators.js is the strictly evaluated "Z" combinator, which needs the extra wrapper around g (g) on the right hand side.

Note that when I use the word "combinator" in this context, it implies "function combinator in the untyped lambda calculus".

@stken2050
Copy link

stken2050 commented Sep 28, 2021

a → b → b is also useful:

const right = a => b => b;
const log = a => right(console.log(a))(a);

This behaves like identity function: a => a which does not affect to the original code but console.log(a) in the process.

It's possible to rewrite with a → b → a

const left = a => b => a;
const log = a => left(a)(console.log(a));

but, It's not intuitive in terms of the evaluation order.

@jethrolarson
Copy link

jethrolarson commented Sep 29, 2021

@stken2050 Fortunately its trivial

const CK = C(K)

I don't see why console.log is a good case though. Maybe you meant 'tap':

const tap = (f) => (x) => {
  f(x);
  return x;
};

tap(console.log)(2)

// Or more usefully: 
doThing().then(tap(console.log))

It is impure though

@stken2050
Copy link

@jethrolarson
Thanks.
Sure, log is IO and impure, and actually, I use the right for any IO operations.

@customcommander
Copy link

Hello! Ramda v0.28.0 has shipped with some new functions, including on: https://ramdajs.com/docs/#on — Do you think we could update the table above?

@drupol
Copy link

drupol commented Jan 25, 2022

It looks like that new on is actually the Psi combinator.

@Avaq
Copy link
Author

Avaq commented Jan 26, 2022

Thanks for the heads-up. Ramda on added to the table! 🎉

@CrossEye
Copy link

CrossEye commented Sep 8, 2022

@JAForbes:

I have this as a pinned tab and I just stare at it sometimes like the obelisk in 2001.

Six years later, and I'm still doing that!

@Avaq: Thank you for a wonderful resource!

@Avaq
Copy link
Author

Avaq commented Sep 15, 2022

Thank you @CrossEye ❤️
I also still commonly refer to this resource, myself. :)

@danwdart
Copy link

Same as gazing avianly at the Smullyan book, which I got in ebook after buying it physically.

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