Skip to content

Instantly share code, notes, and snippets.

@kana-sama
Created October 25, 2019 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kana-sama/edac1458ef223363f6a803af1803e9d2 to your computer and use it in GitHub Desktop.
Save kana-sama/edac1458ef223363f6a803af1803e9d2 to your computer and use it in GitHub Desktop.
type List = readonly any[];
type cons<x, xs extends List> = ((x: x, ...xs: xs) => any) extends ((
...ys: infer ys
) => any)
? ys
: never;
type uncons<ys extends List> = ((...ys: ys) => any) extends ((
x: infer x,
...xs: infer xs
) => any)
? [x, xs]
: never;
type head<ys extends List> = uncons<ys>[0];
type tail<ys extends List> = uncons<ys>[1];
type do_reverse<xs extends List, r extends List> = {
nil: r;
cons: do_reverse<tail<xs>, cons<head<xs>, r>>;
}[xs extends [] ? "nil" : "cons"];
type reverse<xs extends List> = do_reverse<xs, []>;
type do_concat<xs extends List, ys extends List> = {
nil: ys;
cons: do_concat<tail<xs>, cons<head<xs>, ys>>;
}[xs extends [] ? "nil" : "cons"];
type concat<xs extends List, ys extends List> = do_concat<reverse<xs>, ys>;
type do_init<xs extends List, r extends List> = {
nil: never;
one: reverse<r>;
cons: do_init<tail<xs>, cons<head<xs>, r>>;
}[xs extends [] ? "nil" : xs extends [any] ? "one" : "cons"];
type init<xs extends List> = do_init<xs, []>;
type do_inits<xs extends List, result> = {
nil: result;
cons: do_inits<init<xs>, init<xs> | result>;
}[xs extends [] ? "nil" : "cons"];
type inits<xs extends List> = do_inits<xs, xs>;
type drop<n extends List, xs extends List> = {
stop: xs;
step: drop<tail<n>, tail<xs>>;
}[n["length"] extends 0 ? "stop" : "step"];
type a = concat<[1, 2, 3], [4, 5]>;
type b = init<[1, 2, 3]>;
type c = inits<[1, 2, 3]>;
function concat<a extends List, b extends List>(a: a, b: b): concat<a, b> {
return [...a, ...b] as any;
}
function curry<
all_args extends List,
first_args extends inits<all_args>,
result
>(
f: (...all_args: all_args) => result,
...first_args: first_args
): (...last_args: drop<first_args, all_args>) => result {
return (...last_args: drop<first_args, all_args>) => {
return f(concat(first_args, last_args));
};
}
declare function f(a: 1, b: 2): 3;
const f1 = curry(f);
const f2 = curry(f, 1);
const f3 = curry(f, 1, 2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment