Name | # | [Haskell][] | [Ramda][] | [Sanctuary][] | Signature ------------:|-------|----------------|------------|-------------------|---------- identity | **I** | `id` | `identity` | `I` | `a → a` constant | **K** | `const` | `always` | `K` | `a → b → a` apply¹ | **A** | `($)` | `call` | | `(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`² | `ap`² | `(a → b → c) → (a → b) → a → c` psi | **P** | `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. ³) 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. [Haskell]: https://www.haskell.org/ [Ramda]: http://ramdajs.com/ [Sanctuary]: http://sanctuary.js.org/#combinator