/** @module function/compose.ts */ import { init } from '../array/init' import { last } from '../array/last' import { ExtractFunctionArguments, ExtractFunctionReturnValue } from '../helper-types' export function compose( entry: Fn ): ( ...args: ExtractFunctionArguments ) => ExtractFunctionReturnValue export function compose( first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => A export function compose( ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => B export function compose( bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => C export function compose( cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => D export function compose( de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => E export function compose( ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => F export function compose( fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => G export function compose( gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => H export function compose( hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => I export function compose( ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => J export function compose( jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => K export function compose( kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => L export function compose( lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => M export function compose( mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => N export function compose( no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => O export function compose( op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => P export function compose( pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => Q export function compose( qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => R export function compose( rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => S export function compose( st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => T export function compose( tu: ( t: T ) => U, st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => U export function compose( uv: ( u: U ) => V, tu: ( t: T ) => U, st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => V export function compose( vw: ( v: V ) => W, uv: ( u: U ) => V, tu: ( t: T ) => U, st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => W export function compose( wx: ( w: W ) => X, vw: ( v: V ) => W, uv: ( u: U ) => V, tu: ( t: T ) => U, st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => X export function compose( xy: ( x: X ) => Y, wx: ( w: W ) => X, vw: ( v: V ) => W, uv: ( u: U ) => V, tu: ( t: T ) => U, st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => Y export function compose( yz: ( y: Y ) => Z, xy: ( x: X ) => Y, wx: ( w: W ) => X, vw: ( v: V ) => W, uv: ( u: U ) => V, tu: ( t: T ) => U, st: ( s: S ) => T, rs: ( r: R ) => S, qr: ( q: Q ) => R, pq: ( p: P ) => Q, op: ( o: O ) => P, no: ( n: N ) => O, mn: ( m: M ) => N, lm: ( l: L ) => M, kl: ( k: K ) => L, jk: ( j: J ) => K, ij: ( i: I ) => J, hi: ( h: H ) => I, gh: ( g: G ) => H, fg: ( f: F ) => G, ef: ( e: E ) => F, de: ( d: D ) => E, cd: ( c: C ) => D, bc: ( b: B ) => C, ab: ( a: A ) => B, first: ( a: ExtractFunctionReturnValue ) => A, entry: Fn ): ( ...args: ExtractFunctionArguments ) => Z /** * Functional composition, chain applies functions starting from the end and moves left * * @example * const myFormula = compose( add(5), multiply(2) ) * myFormula(10) // 25 * * :: fn |> ... f3 |> f2 |> f1 */ export function compose( ...funcs ) { return ( arg ) => init( funcs ).reduceRight( ( acc, item ) => item( acc ), last( funcs )( arg ) ) } export default compose