In typed Python, how do you type a *args
list that you're expecting to pass to another argument that is a higher kinded function?
For example, this function takes a function and its first argument and internally just routes *args
through, but its type signature depends on the type of that, possibly heterogeneous, argument list:
def curry_one[T, R](x: T, f: Callable[[T, WHAT_GOES_HERE], R]) -> Callable[[WHAT_GOES_HERE], R]:
def curried(*args: WHAT_GOES_HERE) -> R:
return f(x, *args)
return curried
Can Expand be used with a generic type parameter over some kind of heterogeneous array?
(I'm not interested in a curry function in the standard library. I'm writing some specific function adapters and am just using curry as an example.)
You are looking for TypeVarTuple
, which represents an unknown number of types:
def curry_one[T, *Us, R](x: T, f: Callable[[T, *Us], R]) -> Callable[[*Us], R]:
def curried(*args: *Us) -> R:
return f(x, *args)
return curried
def foo(a: int, b: str, c: float, d: bytes) -> None: ...
reveal_type(foo1 := curry_one(0, foo)) # (str, float, bytes) -> None
reveal_type(foo2 := curry_one('', foo1)) # (float, bytes) -> None
reveal_type(foo3 := curry_one(3.14, foo2)) # (bytes) -> None
reveal_type(foo4 := curry_one(b'', foo3)) # () -> None
Do note that all parameter names will be lost and thus arguments can only be passed positionally.