Created
October 25, 2019 14:14
-
-
Save kana-sama/edac1458ef223363f6a803af1803e9d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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