python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.48k stars 2.83k forks source link

[Feature Request] Type Hinting via Lambdas #4880

Closed ryanpeach closed 6 years ago

ryanpeach commented 6 years ago

This may already exist, but I'm noticing some libraries like Numpy have very complicated type checking necessities. My simple solution just comes from multimethods in functional languages: why not use a single variable lambda statement. If it, when evaluated on the input, returns True, it is of that type, otherwise it is not. Example:

def foo(x: lambda x: x.shape == (2,3)):
    pass

This may be reducable to something less wordy:

def foo(x: x.shape == (2,3)):
    pass

Somehow preserving the x name into the type. Perhaps using delayed annotation execution in Python 3.7

Anything like this in the works?

ethanhs commented 6 years ago

I think you are looking for a mix of #3062 (Dependent Types) and #3540, which talks about array shape typing.

ryanpeach commented 6 years ago

@ethanhs I provide shape as an example, albeit a practical one 👍

I draw the feature request primarily from the idea of multimethods from functional languages, where polymorphism has more to do with passing logical assertions. In fact, this would be similar to python's built in assert method, but put in the function annotations themselves (a much more useful place to put them imo.)

ryanpeach commented 6 years ago

Come to think of it, via Python 3.7, wouldn't option #2 be extremely practical? It immediately gets converted into a string on runtime, which then a decorator could turn into a lambda based on the variable name it's assigned to, and then use as type checking assertion when called. Then type checking is as easy as going back to using isinstance and the like.

def foo(x: isinstance(x,int)) -> isinstance(foo, str):
    return "Hello World: {}".format(x)

3062 looks similar, I'm having a bit of trouble following though. The first half they just talk about literal types. Do they go into assertion typing and the like?

gvanrossum commented 6 years ago

Methinks you're a little blurry on the distinction between runtime checking and static checking.

ryanpeach commented 6 years ago

I suppose I am. Does mypy not evaluate at runtime?

ryanpeach commented 6 years ago

Ok, I've freshened up. So, what does mypy do if you do something other than provide a Type from typing as a "type hint" annotation? Like, a string or something. I ask because I may just make something to add runtime typing and try to make it mypy compatible.

Michael0x2a commented 6 years ago

@ryanpeach -- If you use annotations in ways that aren't compatible with PEP 484 (e.g. use something that isn't a type), mypy will treat that as an error. You can tell mypy to ignore that particular method if you annotate it with the typing.no_type_check decorator but then you lose out on the benefits of static type checking entirely (e.g. runtime checks incur a performance penalty, you don't get as strong guarantees about correctness).

If you want to perform these sorts of checks at runtime, you don't need to do anything fancy. You could just use asserts, for example:

def foo(x):
    assert x.shape == (2, 3)
    # ...

If you want something a little more fancy, you could perhaps use libraries like PyContracts.

ryanpeach commented 6 years ago

Pycontracts sounds like what I wanted, thanks!

I'm just exploring what can be done with type hints. You can use them as parameter comments, for static typing, for dynamic typing, or even for space or distribution types like for hyperopt. Some of these are standard and some are not, I thought that PEP 484 made clear that there should be support for mixed types of annotations? Maybe there should just be a way of telling mypy to exclude specific parameters from it's annotation checking, so we can use it along side other use cases for annotations.

ryanpeach commented 6 years ago

Anyway, closing the issue, thanks for your help!

gvanrossum commented 6 years ago

Well this is the mypy issue tracker, so issues about the use of annotations for runtime type checking are not relevant here.