Skip to content

How to declare type variables #1

Closed
@gvanrossum

Description

@gvanrossum

There are two issues around type variables:

  • What function to call a type variable
  • How to specify constraints (and what do the constraints mean)

Currently, mymy uses

T = typevar('T', values=[t1, t2, t3])

while the PEP currently proposes

T = Var('T', t1, t2, t3)

In any case it should be noted in the PEP that this is not the same as

T = Union[t1, t2, t3]

The reason is quite subtle, and the best example is currently the predefined type variable

AnyStr = Var('AnyStr', bytes, str)

Consider a polymorphic function that does something to filenames and works on both bytes and str, e.g.

def extension(file: AnyStr) ->AnyStr:
   return file.rsplit(b'.' if isinstance(file, bytes) else '.', 1)[1]

We really need AnyStr to be a type variable here, because we want to express that if the argument is a bytes, so is the return value, and if the argument is a str, the return value is too.

But that's not all! Such a type variable is constrained to exactly the given types. Consider the case where the argument is an instance of a user-defined subclass of bytes. We don't want the declaration to mean that the return value is then also an instance of that same subclass -- we want it to mean that the return value is a bytes (not a str).

I believe this makes the use of such a type variable equivalent to a collection of overloaded functions; in the above example

def extension(file: bytes) -> bytes:
    ...
def extension(file: str) -> str:
    ...

Open issues:

  • What should the rules be if the type variable is unconstrained?
  • Other languages often have a syntax for specifying a different type of constraint on type variables, e.g. the presence of a certain method; and then the implied type usually does vary with the actually specified type (I think). Do we need a way to do this?
  • Should we name this Var(), typevar(), or something else? (Var() is a PEP 8 violation.)
  • Should the constraints be additional positional arguments, or a keyword argument? If the latter, what should it be named?

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