// @flow export type Predicate = (a: A) => boolean; export type Fn1 = (a: A, ...rest: Array) => B; export type Fn2 = (a: A, b: B, ...rest: Array) => C; export type Fn3 = (a: A, b: B, c: C, ...rest: Array) => D; export type Fn4 = (a: A, b: B, c: C, d: D, ...rest: Array) => E; export type Fn5 = (a: A, b: B, c: C, d: D, e: E, ...rest: Array) => F; export type Fn6 = (a: A, b: B, c: C, d: D, e: E, f: F, ...rest: Array) => G; export type Fn7 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, ...rest: Array) => H; export type Fn8 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, ...rest: Array) => I; export type Fn9 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, ...rest: Array) => L; export type Endomorphism = Fn1; declare function compose(bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(de: Fn1, cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(fe: Fn1, de: Fn1, cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(fg: Fn1, fe: Fn1, de: Fn1, cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(fh: Fn1, fg: Fn1, fe: Fn1, de: Fn1, cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(fi: Fn1, fh: Fn1, fg: Fn1, fe: Fn1, de: Fn1, cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function compose(fj: Fn1, fi: Fn1, fh: Fn1, fg: Fn1, fe: Fn1, de: Fn1, cd: Fn1, bc: Fn1, ab: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, de: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, de: Fn1, ef: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, de: Fn1, ef: Fn1, fg: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, de: Fn1, ef: Fn1, fg: Fn1, gh: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, de: Fn1, ef: Fn1, fg: Fn1, gh: Fn1, hi: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare declare function pipe(ab: Fn1, bc: Fn1, cd: Fn1, de: Fn1, ef: Fn1, fg: Fn1, gh: Fn1, hi: Fn1, ij: Fn1, ...rest: Array): Fn1; // eslint-disable-line no-redeclare export type CurriedFn2 = & Fn1> & Fn2; export type CurriedFn3 = & Fn1> & Fn2> & Fn3; export type CurriedFn4 = & Fn1> & Fn2> & Fn3> & Fn4; export type CurriedFn5 = & Fn1> & Fn2> & Fn3> & Fn4> & Fn5; declare function curry(f: Fn2): CurriedFn2; // eslint-disable-line no-redeclare declare function curry(f: Fn3): CurriedFn3; // eslint-disable-line no-redeclare declare function curry(f: Fn4): CurriedFn4; // eslint-disable-line no-redeclare declare function curry(f: Fn5): CurriedFn5; // eslint-disable-line no-redeclare // Flips the order of the arguments to a function of two arguments. export function flip(f: (a: A, b: B) => C): (b: B, a: A) => C { return (b, a) => f(a, b) } // Returns its first argument and ignores its second. export function constant(a: A): (b: B) => A { return () => a } // The `on` function is used to change the domain of a binary operator. export function on(o: (x: B, y: B) => C, f: (a: A) => B): (x: A, y: A) => C { return (x, y) => o(f(x), f(y)) } export function compose(...fns) { // eslint-disable-line no-redeclare const len = fns.length - 1 return x => { let y = x for (let i = len; i > -1; i--) { y = fns[i].call(this, y) } return y } } export function pipe(...fns) { // eslint-disable-line no-redeclare const len = fns.length - 1 return x => { let y = x for (let i = 0; i <= len; i++) { y = fns[i].call(this, y) } return y } } function curried(f, length, acc) { return function () { const combined = acc.concat(Array.prototype.slice.call(arguments)) return combined.length >= length ? f.apply(this, combined) : curried(f, length, combined) } } export function curry(f: Function) { // eslint-disable-line no-redeclare return curried(f, f.length, []) }