import curryN from './utils/curry_n.ts';import type { Func, PH } from './utils/types.ts';import { reduce } from './reduce.ts';import { ap } from './ap.ts';import { map } from './map.ts';import { tail } from './tail.ts';
type LiftN_2 = (fn: Func) => Func;
type LiftN_1 = (arity: number) => Func;
type LiftN = & ((arity: number) => LiftN_2) & ((arity: PH, fn: Func) => LiftN_1) & ((arity: number, fn: Func) => Func);
function _liftN(arity: number, fn: Func): Func { const lifted = curryN(arity, fn); const f = function () { const args = tail(arguments); const mapped = (map(lifted, arguments[0]) as any) as Func[]; return reduce(ap, mapped, args); }; return curryN(arity, f);}
export const liftN: LiftN = curryN(2, _liftN);