Typing custom integer class

In practice when it comes to numeric types you could never really just rely on duck-typing as a general approach. I’m sure it is the same in SageMath as in other libraries where for SymPy, NumPy etc every public function has to convert every potentially numeric input parameter to its own numeric types:

def public_func(x):
    x = convert_to_known_types(x)
    # Now do stuff with x

With or without static typing that is needed because you have to validate the inputs and the different numeric types that might be passed in just aren’t interchangeable (otherwise we wouldn’t have so many of them!).

Take the function Tobias showed:

def func(y: int) -> str:
    return str(y + 1)

Now

In [3]: func(255)
Out[3]: '256'

In [4]: func(np.uint8(255))
Out[4]: '0'

(It also prints an overflow warning but I omit that to show the output clearly.) Now there are situations where you do actually want to get '0' out there but clearly there are also many situations where it would be totally wrong.

If the author of func wants it to work predictably then they either need to have control over what y + 1 means by controlling the type of y or otherwise it needs to be clear that the caller’s type is allowed to control that behaviour and therefore defines the meaning of func itself (some kind of generic code).

The Integer type we are talking about here is an example of this. Division with Integer gives Rational not float. You don’t actually want to write code that does arithmetic with a variable of type Integer | int because the whole point of Integer is that it behaves differently to int even in basic arithmetic.

1 Like