Common combinators in JavaScript
January 5, 2024 · View on GitHub
| 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-point⁴ | 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.
⁴) 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.