Re: Thoughts on a NotType?
![](https://secure.gravatar.com/avatar/221e3d19845cd594f3b4f6a11ceeffb5.jpg?s=120&d=mm&r=g)
(Hoping I figured out how to reply in the thread now... ) Yes, sorry for the cryptic message but it looks like you got it right. The example isn't impressive but just like Steven is saying the value comes in larger applications. In a web application for instance only the parsing layer will have to deal with the runtime validation of the type. The business logic and database layers can use static type checking to make sure only the narrowed value is allowed. So it's kind of like a NewType plus an "instantiation predicate" (I'm failing to find the correct term, nothing is actually instantiated). I thought it's relevant here since I imagine a NotType would also have to rely a lot on runtime narrowing. If a downstream API takes Sequence & Not[str] and we have a Sequence available, we'd have to narrow it with something like assert not isinstance(..., str).
![](https://secure.gravatar.com/avatar/047f2332cde3730f1ed661eebb0c5686.jpg?s=120&d=mm&r=g)
On Fri, Dec 24, 2021 at 9:38 AM Anton Agestam <antonagestam@gmail.com> wrote:
(Hoping I figured out how to reply in the thread now... )
(Almost. Your message came through (we have moderation for new list members because of insistent spammers) but my mail reader doesn't show it in the same thread. That happens a lot so let's not worry about it.)
Yes, sorry for the cryptic message but it looks like you got it right. The example isn't impressive but just like Steven is saying the value comes in larger applications. In a web application for instance only the parsing layer will have to deal with the runtime validation of the type. The business logic and database layers can use static type checking to make sure only the narrowed value is allowed. So it's kind of like a NewType plus an "instantiation predicate" (I'm failing to find the correct term, nothing is actually instantiated).
Let me see if I understand what happens here ( https://github.com/antonagestam/phantom-types/blob/main/README.md#examples), without trying to understand the source code: class Name(str, Phantom, predicate=contained({"Jane", "Joe"})): ... greet(Name.parse("Jane")) To the static type checker (mypy, Pyre, pyright etc.) the argument to greet() has type Name, which is a class. But at runtime its __class__ is just str -- but through the magic of __instancecheck__, isinstance("Joe", Name) still returns True. This is indeed cool. It's also cool that because of the isinstance() trick, static checkers will narrow the type correctly after 'if isinstance(x, Name)' or 'assert isinstance(x, Name)'. I suppose there's some caching going on as well? (Throwing in an lru_cache somewhere would seem easy and I can't see a downside.) I'm curious if this is still useful if you want to parse a longer string into components. Could this be made to parse a long string into an HTTP header struct returning a dic[str, str] (or whatever data structure is appropriate)?
I thought it's relevant here since I imagine a NotType would also have to rely a lot on runtime narrowing. If a downstream API takes Sequence & Not[str] and we have a Sequence available, we'd have to narrow it with something like assert not isinstance(..., str).
That makes sense, although the more likely scenario is that the value we have in hand is known to be a list[str], for example. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>
![](https://secure.gravatar.com/avatar/3247bfd67c8fa4c4a08b8d30e49eab39.jpg?s=120&d=mm&r=g)
I haven't heard the term "phantom type" previously, but I like the idea. It's conceptually simple and yet quite powerful. Anton, it looks like this is a relatively new library. What has the feedback been so far? Is it getting significant uptake? Do you know if it has been adopted in any large code bases other than your own? If I understand the motivations behind the "NotType" proposal, it seems to me that phantom types could solve most (all?) of the intended use cases without all of the downsides that I previously raised. Are there any changes to the current type system, the runtime, or the current static type checker implementations that are needed to support phantom types? From the above discussion and the documentation , it sounds like the answer might be "no". -Eric
![](https://secure.gravatar.com/avatar/5dc484e83f87a994a4c21c21e8b9c1b0.jpg?s=120&d=mm&r=g)
I have been using Anton's library for quite some time now. Mostly together with my own library: typeclasses (FP concept) https://classes.readthedocs.io/en/latest/pages/concept.html#delegates It is a great tool. I can highly recommend it. The main problem is that it does not work with mutable types by design. Why? What? For example, you want to write a phantom type called "ListOfPositiveInt". So it can be used like so: `isinstance(arg, ListOfPositiveInt)`. But, the problem is: `list` is mutable. After this check passes, you can call `arg.append(-100)` and ruin your precise type. That's why it is limited to immutable types only. сб, 25 дек. 2021 г. в 02:22, Eric Traut <eric@traut.com>:
I haven't heard the term "phantom type" previously, but I like the idea. It's conceptually simple and yet quite powerful. Anton, it looks like this is a relatively new library. What has the feedback been so far? Is it getting significant uptake? Do you know if it has been adopted in any large code bases other than your own?
If I understand the motivations behind the "NotType" proposal, it seems to me that phantom types could solve most (all?) of the intended use cases without all of the downsides that I previously raised.
Are there any changes to the current type system, the runtime, or the current static type checker implementations that are needed to support phantom types? From the above discussion and the documentation , it sounds like the answer might be "no".
-Eric _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: n.a.sobolev@gmail.com
![](https://secure.gravatar.com/avatar/2d7bf905fe3f737ee2cb80d7fb67b684.jpg?s=120&d=mm&r=g)
I just merged a SequenceNotStr type into phantom-types, I'll release that in 0.16 soon. https://phantom-types.readthedocs.io/en/main/pages/types.html#module-phantom... https://github.com/antonagestam/phantom-types/pull/194 Sorry for the lack of response to your questions in this thread.
What has the feedback been so far? Is it getting significant uptake? Do you know if it has been adopted in any large code bases other than your own?
No not really, there has been some interest but nothing I would call a significant uptake. We are using it in large code bases at work and thus far we've seen no problems. There hasn't been that many interactions on Github, but I've received some nice feedback and input from Nikita.
Are there any changes to the current type system, the runtime, or the current static type checker implementations that are needed to support phantom types? From the above discussion and the documentation , it sounds like the answer might be "no".
Yeah, my library uses the __instancecheck__ interface, but as have been suggested in other threads, using NewType and TypeGuard is possible too. So I agree, the answer is "no".
I suppose there's some caching going on as well? (Throwing in an lru_cache somewhere would seem easy and I can't see a downside.)
There isn't currently, I'd be a little bit wary doing that since it could make large objects live in memory longer than a user expect them to. And perhaps especially since a main usecase is validating web requests. Or does lru_cache clean up values when they have no other references?
participants (5)
-
Anton Agestam
-
Anton Agestam
-
Eric Traut
-
Guido van Rossum
-
Никита Соболев