Skip to content

Types as function namespaces #5980

@jesaerys

Description

@jesaerys

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions