-
Notifications
You must be signed in to change notification settings - Fork 256
Decide meaning of alias with one generic and one concrete parameter #115
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
Comments
Addresses, but does not fix, #115.
On second thoungt I don't think we need language for aliases (they just mean whatever the expression on the RHS would mean in the context where the alias is used) but I added language clarifying that defining a class that inherits from This is not fixed in typing.py, so keeping the "bug" label. |
Here are some examples to make sure I understand the feature right. Consider these definitions:
Now these two signatures would be equivalent:
Also, these two would be equivalent:
These would be errors:
|
No, for f, T is the dict's value type, while for g, T is the dict's key type. Maybe you meant this?
Those are indeed equivalent.
Why would that be an error? It just means (to me) that x is a dict with
This example is the crux of the issue. The current implementation in
If you agree, can you update the PEP and then reassign to me so I can fix |
I must say that the idea to have both: Dict[int, str]
Dict[int][str] means that generics have a very intuitive semantics, this is the same as for normal functions, normal variables, and partial application. With this generics feel like real first class members of the language. It would be cool to have this. |
Unfortunately I think I misspoke. I think allowing
And this should work too:
|
I agree, if one has two parameters, one must specify which parameter to fix, first or second. |
I'm also in favor of the latest proposal. Allowing for currying would be another concept on top of something that might already be confusing.
|
Jukka, if you have time for this, it would be good to write this up in the PEP (if you think we've arrived at a workable and unambiguous proposal). |
I won't be able to do it today, sorry, at least until the evening. — On Fri, May 22, 2015 at 7:34 AM, Guido van Rossum
|
So let me summarize where this is. The PEP says that this should work:
and that now The PEP does not specify whether the following is allowed (it isn't supported by typing.py):
I propose that both should work. (But I still have some misgivings about the latter; see below.) I also propose that this should not work:
The only ways to start with a generic type of N parameters and end up with a generic type of fewer but not zero parameters is to either subclass or create an alias from it, using concrete types for some parameter slots and type variables for other slots. Also, while the following is allowed:
the alias A must still be used with two parameters (each bounded by the corresponding parameter to Dict) and A cannot be used as a base class for a generic class. (This makes |
I don't think the example with T = TypeVar('T')
S = TypeVar('S')
class MyMap(Mapping[Tuple[T, S], str]): ... could be useful. In general: making a type more specific does not always mean reducing the number of type parameters. The above example currently fails with
Maybe |
@gvanrossum I noticed that your example added to PEP contains |
I know! I'm looking into it but it's a somewhat tricky change. I'm going on vacation until April 4th and I don't expect I'll get to it before then. It will be done before Python 3.5.2 is released. |
I expect I'll have to redesign and rewrite a large swath of typing.py. Here are some early thoughts on the design: How this SHOULD work
Possible algorithm
|
Not to tease too much, but I think I've got this implemented. However JetBlue's free wifi apparently blocks git (though web traffic goes through). Once I'm on the ground I'll push a branch so you can kick the tires. |
Everything looks logical. At first reading I didn't find any problems or inconsistencies. Concerning your bullet number 3: I think it is better to require the same total number of parameters plus concrete types (including class C(Generic[T1,T2]): ...
class D(C[Any, S]): ... Concerning the choice between (e1) and (e2) I vote for (e1). I could imagine a situation when some library provides a generic class that is in fact indexed, so that if we prohibit further indexing users will have quite limited options and get unexpected errors. Also from the point of view of your algorithm I do not see a difference between "normal" generic and an "indexed" one, at the last step in the class constructor you create an un-indexed generic (and I think this is a good simple choice). Looks like there is a big piece of work ahead. It would be great if you implement all the logic that you described. |
Wow! That is fast. |
Pushed. Review away! |
Finally got around to reading the proposal -- it looks good, though the language feels a little vague at places. Making the definitions very rigorous would likely make them harder to read, so you may prefer to leave them as they are. I haven't looked at the implementation update yet. |
Which language is vague? The long comment I wrote in this issue? That was really just me trying to understand the intention of the PEP and figuring out how to implement it. Or the language in the PEP? That could use some tightening up so others won't fall in the same trap I fell into when I wrote the earlier implementation. But I'm blind for its vagueness now, so someone will have to propose specific edits. |
It was about the long comment above. If it's only for this discussion then
|
OK. FWIW the implementation goes with (e1), but that elicited the only feedback so far: #195 (comment) (my tentative response is right below it). |
See python/mypy#606. We allow the following, and they are well-defined:
But what does this mean?
In typing.py this currently defines Z as something with two parameters, the second constrained to int or subclasses thereof. But another reasonable interpretation would be that Z has one parameter, corresponding to T only.
The second interpretation is actually more reasonable. (As long as we require that all parameters are either concrete or a simple type variable, not another type expression or alias containing a type variable.)
If we agree, we should define this in the PEP and implement it in typing.py.
The text was updated successfully, but these errors were encountered: