Skip to content

Will recursive or mutually recursive bounds on TypeVar be supported? #1561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
smallnamespace opened this issue May 20, 2016 · 6 comments
Open

Comments

@smallnamespace
Copy link

smallnamespace commented May 20, 2016

Reading through the discussion at python/typing#59, there was an example that had TypeVar bound that referenced itself. Is this intended to be eventually implemented? The actual PEP just has a bare Comparable.

A motivating example (from the Java world) is discussed here, in the context of their Enum. An example in Python:

from typing import Generic, Optional, Tuple, TypeVar  

# Would like to write bound='TypedCons[T, V]' here, where T is self-referential
T = TypeVar('T', bound='TypedCons')
V = TypeVar('V')  


class TypedCons(Generic[T, V]):  
    def __init__(self, value: V, cdr: Optional[T]=None) -> None:  
        self.value = value  
        self.cdr = cdr  

    def first_two(self) -> Tuple[T, T]:  
        # Fails without cast with "Incompatible return value type: expected Tuple[T`1, T`1], got Tuple[example.TypedCons[T`1, V`2], T`1]"  
        return self, self.cdr  

class IntCons(TypedCons['IntCons', int]):  
    pass

# Recursive bound would reject this
class BadCons(TypedCons['IntCons', str]):  
    pass  

If I try to write the recursive bound, I get:

example.py:3: error: Invalid type "example.T"

A similar example where this is needed is at https://github.com/smallnamespace/pymcts/blob/b5e1375e67983ef7b5baa2511c680074fd31b00c/pymcts/tree.py#L78 -- here we need to use the fact that N and Node are identical.

@smallnamespace
Copy link
Author

@gvanrossum @JukkaL

Reading through python/typing#59 again, it seems like the recursive reference is the same thing as F-bounded polymorphism, which you want to hold off on.

Just curious, is that due to the difficulty in implementing the checker properly, or in using bounded quantification correctly?

@gvanrossum
Copy link
Member

gvanrossum commented May 30, 2016 via email

@smallnamespace
Copy link
Author

smallnamespace commented May 30, 2016

This paper suggests a straightforward implementation, but it'll take awhile for me to wrap my ahead around mypy's codebase. Would it make it into the PEP if mypy supported it?

Note that realistic f-bounded polymorphism implementations would have restrictions on what can be written, because the completely general case (with variance) is undecidable. The paper above makes type checking tractable by splitting types in 'shapes' and 'materials'.

@gvanrossum
Copy link
Member

Probably.

On Mon, May 30, 2016 at 10:52 AM, smallnamespace notifications@github.com
wrote:

This paper
http://www.cs.cornell.edu/%7Eross/publications/shapes/shapes-pldi14-tr.pdf
suggests a straightforward implementation, but it'll take awhile for me to
wrap my ahead around mypy's codebase. Would it make it into the PEP if mypy
supported it?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#1561 (comment), or mute
the thread
https://github.com/notifications/unsubscribe/ACwrMpdEN-8eWRTa9bJPobwdkkrjQ4Uxks5qGyPDgaJpZM4Ijc1v
.

--Guido van Rossum (python.org/~guido)

@JukkaL
Copy link
Collaborator

JukkaL commented May 30, 2016

When I looked into this it seemed like this wouldn't quite work for perhaps the most common potential use (Comparable[T]) because of the semantics of operator methods (reverse methods, etc.). Thus I wasn't aware of many interesting use cases where this would actually work, whereas there were a lot of other potential features missing or broken that had well-known use cases (and still are). However, if the implementation isn't complex we'd probably accept a PR.

@erictraut
Copy link

I think mypy is doing the right thing here. The above code sample clearly exhibits a type violation, for a couple of reasons:

  1. The type of self is not necessarily T. The type of T could be a different subtype of TypedCons.
  2. The type of the expression self.cdr is not T, it's T | None.

I recommend closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants