Why can't we ...?

Another typing syntax suggestion discussed multiple times (@Jelle also seems to have posted on most of them!) is that of “type intersections”: what does it mean to say A & B

There are lots of search results for this topic. There is also a very long discussion on github complete with some examples. There is even PEP 742 which seems to suggest that the concept can already be achieved by TypeIs?

I can’t say I’ve read them all in huge detail, but I’m surprised we don’t have the syntax yet and would enjoy reading a similar review on your blog post :slightly_smiling_face:

I felt intersections are out of scope for this document, because I wanted to focus on syntactic changes that could make the type system more ergonomic. Intersections instead would be a big new type system feature, not something I can do justice to in the format used in the article.

3 Likes

I think most of these why-nots can be resolved if we allow TypeExpr-specific constructors. This should not create much obfuscation for the syntax because these statements would otherwise not be valid TypeExpr anyway.

It also requires very minimal changes to the documentation because on user side these are very natural and intuitive syntaxes, likely aligned with their expectations.

For example:

1 => int(1) # Normal expr
1 => Literal[1] # TypeExpr

(A, B) => tuple((A, B)) # Normal expr
(A, B) => Tuple[A, B]   # TypeExpr

{"a": int} => dict({"a": int}) # Normal expr
{"a": int} => TypedDict[...] # TypeExpr

By “TypeExpr-specific constructors” I mean python interpreter will invoke typing-specific constructor on these expressions during byte code generation.


For the “Literal” example, a deal-breaker would be recursion hell. But I bet there is a solution out there.

1 => Literal[1] => Literal[Literal[1]] => ...

Upon second thought, as long as user adheres to the new syntax (i.e. 1 instead of Literal[1]), there will be no recursion at all. Worst case is Literal[1] expanded to Literal[Literal[1]] - which is fine.


Another deal breaker: string literals conflicts with forward references. Possible solution will be use different types of quotes to distinguish them, but I anticipate a ton of opinions against it.

If I’ve involved in the discussion for forward reference, I guess one proposal I would give is to re-enable back-qoutes for deferred expression. This might also benifit defer-expressions. But it feels too late to even open up such discussion.