Open drvink opened 8 years ago
I agree that there should be a single SignatureType. Note that arrow type is not enough, since signatures in Python are more complex. SignatureType should have a binding operation, which will easily handle most uses of partial
, and may also make hellp SelfType (#1212) "fall out of the implementation".
(I also do not understand why an overloaded function is not simply a Union of SignatureTypes)
An overloaded function could perhaps be an intersection of signatures, but even then they are currently not quite intersection types, since the order of signatures is significant, whereas intersection types are commutative.
It can't be a union since then a call would be valid only if it was compatible with every component signature.
@JukkaL thanks I got it backwards indeed...
Why don't we have an intersection type yet? And thinking about it, if fallback means intersection, it happens to be ordered too. And so does multiple inheritance.
Yes, an ordered intersection type could perhaps replace overloaded callables and fallbacks -- not sure about multiple inheritance. I think about it every once in a while but I've never spent much time thinking about the implications. It would likely be a big change, and until we can demonstrate a concrete net benefit it's unlikely to happen. Also, there could be some edge cases that it doesn't deal well with -- it's possible that it would make some things cleaner and other things messier.
Introducing it incrementally may help in assessing its value.
I think that a concrete benefit will be the ability to understand the code, especially fallbacks.
I'm not sure if this smaller example is part of this issue or something different, but I'm having trouble getting Callable[..., T] to unify with a concrete type.
T = TypeVar("T", covariant=True)
f: Optional[Callable[[str], T]] = None
f = lambda x: str(x)
This fails with:
Incompatible types in assignment (expression has type "Callable[[str], str]", variable has type "Optional[Callable[[str], T]]")
Is there a way to workaround this issue? If there is a better place for this discussion, let me know.
@alunduil Your issue seems different from the original issue. It would be great if you could open a new GitHub issue about it.
Here's my analysis anyway:
f
basically seems to have an existential type in your example (Optional[Callable[...]]
for some T
). Unfortunately, mypy doesn't support existential types, and mypy should actually complain about the type annotation of f
instead of the assignment.
The closest supported type might be Optional[Callable[[str], object]]
. You can always fall back to Optional[Callable[[str], Any]]
, but it's less precise.
(Also, I think the example lambda is a Callable[[T], str]
, not Callable[[str], T]
.)
@JelleZijlstra, It's Callable[[T₂], str]
going into a Callable[[str], T₁]
which should be unifiable (and might be the problem), but I'll document all of this in another issue so we don't pollute this one.
See
XXX
comments for highlights.Callable[..., T]
:partial
:As an aside,
Callable
and especiallypartial
are very clumsy to use withtyping
; the use of higher-order functions is greatly impaired. The fact thatdef
is notCallable
is notlambda
is notpartial
is not any number of other things vs. having a single simple ML-style arrow type is unfortunate.