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 P = f => g => x => y => f(g(x))(g(y)); const Y = f => (g => g(g))(g => f(x => g(g)(x)));
¹) 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.
Note that when I use the word "combinator" in this context, it implies "function combinator in the untyped lambda calculus".