1
from typing import Tuple, TypeVar, Any

ParamArray = TypeVar("ParamArray", Tuple[Any, ...])

The concept is; a ParamArray is just a tuple of values. I have a function

def integrate(func, a, b, args=()):
    delta = 0.1
    running_total = 0.
    for x in range(a, b, step=delta):
        running_total += func(x, args) * delta
    return running_total

As such I was trying to type it:

def integrate(func:Callable[[float, ParamArray], float], a: float, b: float, args: ParamArray=()) -> float:

to try and convey the fact that the args ParamArray is the same thing that gets passed to func so the callback must be able to accept whatever args are passed.

I'm getting a few errors

TypeVar cannot have only a single constraint
Argument 2 to "TypeVar" has incompatible type "object"; expected "Type[Any]"
Variable "typealiases.ParamArray" is not valid as a type
Greedo
  • 4,967
  • 2
  • 30
  • 78

1 Answers1

1

First off, As a and b are going to be used in the range object, they should be int not float. Also step= should be int too,so delta have to be int as well.

See this post : click

a TypeVar is a variable you can use in type signatures so you can refer to the same unspecified type more than once, while a NewType is used to tell the type checker that some values should be treated as their own type.

The error you are getting is because you can't have one constraint in TypeVar, in your case a single Tuple.

Actually you want that your func's arguments to be an instance of Tuple of something(or a subclass of Tuple) and then the args argument be the exact same tuple. This can be done using bound= argument in TypeVar.

from typing import Tuple, TypeVar, Any, Callable

ParamArray = TypeVar("ParamArray", bound=Tuple[Any, Any])


def integrate(func: Callable[[ParamArray], float], a: int, b: int,
              args: ParamArray = ()) -> float:
    delta = 1
    running_total = 0.
    for x in range(a, b, step=delta):
        running_total += func(x, args) * delta
    return running_total


def fn1(t: Tuple[int, int]) -> float:
    pass

def fn2(t: Tuple[float, float]) -> float:
    pass

integrate(fn1, 10, 20, (1, 2))      #valid
integrate(fn2, 10, 20, (1.1, 2.2))  #valid
integrate(fn1, 10, 20, (1.1, 2.2))  #invalid

Now in the third case, you can see because fn1 takes tuple of integers and we passed tuple of floats to the args parameter, it complains. (I know you will test the reversed situation with fn2 passing tuple of integers and he doesn't complain. That's because an integer is also a float in type hints).

S.B
  • 13,077
  • 10
  • 22
  • 49