-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
I often wish that types could also be namespaces for functions. To motivate this idea, let me start with a simple example. Say I need some functions that apply to arbitrary 2-tuples. The simplest solution is to write a module defining a Pair
type along with the functions I need:
# pair.py
from typing import Tuple, TypeVar
A = TypeVar('A')
B = TypeVar('B')
Pair = Tuple[A, B]
def fst(pair: Pair[A, B]) -> A:
a, _ = pair
return a
def snd(pair: Pair[A, B]) -> B:
_, b = pair
return b
I would use my module like this:
# test.py
import pair
from pair import Pair
def f(p: Pair[int, float]) -> float:
return pair.fst(p) + pair.snd(p)
p: Pair[int, float] = (1, 1.5)
assert f(p) == 2.5
This works and it typechecks with mypy. However, naming is a bit cumbersome with this approach. I can't use the pair
identifier for Pair
variables because I've already used it for my module, and I'm forced to resort to something like p
instead. Also, it would be nicer if the functions fst
and snd
had a clearer association with the type Pair
.
I'd much rather write something like this for my test:
# test.py
from pair import Pair
def f(pair: Pair[int, float]) -> float:
return Pair.fst(pair) + Pair.snd(pair)
pair: Pair[int, float] = (1, 1.5)
assert f(pair) == 2.5
where Pair
is now both a type and a namespace for associated functions.
Is it possible for mypy to support this?
I'm not making any syntax proposals here, but I'll note that the following does work at runtime:
from typing import Tuple, TypeVar
A = TypeVar('A')
B = TypeVar('B')
class Pair(Tuple[A, B]):
def fst(pair: Pair[A, B]) -> A:
a, _ = pair
return a
def snd(pair: Pair[A, B]) -> B:
_, b = pair
return b
def f(pair: Pair[int, float]) -> float:
return Pair.fst(pair) + Pair.snd(pair)
pair: Pair[int, float] = (1, 1.5)
assert f(pair) == 2.5
Unfortunately, it does not typecheck with mypy, first of all because generic tuples are not allowed (#685). Second, even if generic tuples were supported, my assignment statement for pair
would fail with an "Incompatible type" error because the expression has type Tuple[int, float]
while the variable has type Pair[int, float]
, and mypy sees Pair
as a subtype of Tuple
due to the class definition.
I'm really curious to hear people's thoughts on this.
Thanks.