functional annotation of polymorphic functions

Viewed 161

Say that I've got a polymorphic function that repeats any object passed into it as an argument (similar to the itertools.repeat from the Python Standard Library):

def repeat(i):
    while True:
        yield i

How do I write function annotation that tells that this is a polymorphic function?

Let me be clear, I understand that one possibility is to write:

from typing import Any, Iterable


def repeat(i: Any) -> Iterable[Any]:
    while True:
        yield i

This solution is, however, ambiguous because it's true for the both of the following case:

repeat(i: Apples) -> Iterator[Apples]:

or

repeat(i: Apples) -> Iterator[Oranges]:

I would like to have a solution that truly reflects to the fact that the function accepts any type but that it gives back an iterator which produces the same type used for calling the function.

As an example from Haskell, this would be solved using type variables and the function type in Haskell would simply be:

repeat :: a -> [a]

where a is a type variable. How wold I get the same result in Python?

1 Answers

There is a very similar example in the Python docs using TypeVar:

def repeat(x: T, n: int) -> Sequence[T]:
    """Return a list containing n references to x."""
    return [x]*n

where T = TypeVar('T') # Can be anything is used. So you can adapt this:

from typing import Iterable, TypeVar

T = TypeVar('T')

def repeat(i: T) -> Iterable[T]:
    while True:
        yield i
Related