Generics over container types? (original) (raw)

Given that I have a function:

def process[T](collection: Sequence[T]) -> Sequence[T]

I want to express that, when the input is of type list[T], the return value will be list[T], when the input is of type tuple[T, ...], the return value will be tuple[T, ...]. Its means that the container type (list, tuple, Deque) of the return value is in accordance with the input.

How should I make type annotation?

Daverball (David Salvisberg) June 9, 2025, 2:24pm 2

That’s what upper bounds in a TypeVar are for, in your simple example, you should be able to express it like this:

def process[T: Sequence](collection: T) -> T: ...

quan (Nguyễn Hồng Quân) June 9, 2025, 2:31pm 3

Thank you, how to annotate the element type also, like Sequence[U]? Is this valid:

def process[T: Sequence[U]](collection: T) -> T: ...

Daverball (David Salvisberg) June 9, 2025, 3:42pm 4

No, this requires higher kinded types, which are not supported yet.

jorenham (Joren Hammudoglu) June 9, 2025, 4:33pm 5

Technically speaking this isn’t HKT, but rather a generic type-parameter bound.

Also note that in this example U only appears once, so there is no need for it. So even if Python would support generic type-parameter bounds or HKT, then the above would be equivalent to:

def process[T: Sequence[object]](collection: T) -> T: ...

So this already works :slight_smile: