typing icon indicating copy to clipboard operation
typing copied to clipboard

Allow to use function objects as singletons

Open Jackenmen opened this issue 6 years ago • 6 comments

I was trying to create some stubs for lxml library, but I encountered a function that depending on a function object it gets (as in specific function object - checked with identity check) only finds objects of specific type.

Here's a very simplified mock-up of it so that you can get some idea on what I mean (the typing for arg argument in the find function is incorrect and that's what I want to be able to type hint in some way):

from typing import Union

class _Element: ...

def Element() -> _Element: ...

class _Comment: ...

def Comment() -> _Comment: ...

def find(arg: Union[Element, Comment]) -> Union[_Element, _Comment]:
    if arg is Element:
        # only find _Element objects
    elif arg is Element:
        # only find _Comment objects

# this function should only accept `Element` and `Comment` function object 
find(arg=Element)

So basically those functions serve as a singletons. Unfortunately typing.Union only allows Enums to work as singletons.

I am not entirely sure if this should be supported, usually the code could just be adjusted to use Enums, but in this case it will be used for type stubs so the code can't be edited. And to be honest, I am not sure if the code really needs editing in that case as if I didn't need typing for that library, I would say it's actually quite intuitive to use these factory functions as arguments in this case.

Jackenmen avatar Aug 21 '19 18:08 Jackenmen

I recommend that you try the work-around you suggested yourself and use it for a while, then tell us how bad (or not) that was. Implementing this in mypy would probably be a significant project, which means it won't happen soon.

gvanrossum avatar Aug 21 '19 21:08 gvanrossum

Thanks for quick answer. If you mean the Enum workaround then unfortunately like I said, I created this issue with type stubs in mind - I am not lxml developer and I just wanted to help create proper type stubs for lxml (JelleZijlstra/lxml-stubs) I know very well that this wouldn't happen any time soon, I just wanted to know if such addition may happen some day or if it's rather something that you would rather want to not implement.

Jackenmen avatar Aug 21 '19 22:08 Jackenmen

Honestly I think it's rather an odd corner case -- why function objects and not class objects? Perhaps the best way to think about this is PEP 586 (Literal types) -- are there other objects that we could support inside the brackets of Literal[...]? @Michael0x2a

gvanrossum avatar Aug 21 '19 23:08 gvanrossum

In case this would actually be class object, I don't think there's a way to type a class object without including subclass objects? (which would be required if it were supposed to be used in code that uses simple identity check)

Jackenmen avatar Aug 21 '19 23:08 Jackenmen

Well, if we're in the realm of hypothetical type system features, we could say that Literal[SomeClass] means exactly that class object, while Type[SomeClass] means that class object or a subclass.

JelleZijlstra avatar Aug 21 '19 23:08 JelleZijlstra

Before I fully read PEP 586, I even thought that such use is going to be possible with Literal types.

Jackenmen avatar Aug 22 '19 00:08 Jackenmen