GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Higher-Kinded TypeVars · Issue #548 · python/typing

Higher-Kinded TypeVars #548

New issue
Copy link
New issue
Copy link
Open
Open
Higher-Kinded TypeVars#548
Copy link
Labels
topic: featureDiscussions about new features for Python's type annotationsDiscussions about new features for Python's type annotations

Description

@tek
tek
opened on Mar 30, 2018
Issue body actions

aka type constructors, generic TypeVars

Has there already been discussion about those?
I do a lot of FP that results in impossible situations because of this. Consider an example:

A = TypeVar('A')
B = TypeVar('B')
F = TypeVar('F')

class M(Generic[F[X], A]):
    def x(fa: F[A], f: Callable[[A], B]) -> F[B]:
        return map(f, fa)

M().x([1], str)

I haven't found a way to make this work, does anyone know a trick or is it impossible?
If not, consider the syntax as a proposal.
Reference implementations would be Haskell, Scala.
optimally, the HK's type param would be indexable as well, allowing for F[X[X, X], X[X]]


Summary of current status (by @smheidrich, 2024-02-08):

  • @JelleZijlstra has indicated interest in sponsoring a PEP, conditional on a prototype implementation in a major type checker and a well-specified draft PEP.
  • Drafting the PEP takes place in @nekitdev's fork of the peps repo. The stub PEP draft so far contains a few examples of the proposed syntax.
  • That same repo's GitHub Discussions forum forum has been designated as the place to discuss the PEP (and presumably the prototype implementation?). Some limited further discussions have taken place there.
    • If you want to be notified of new discussion threads, I think you have to set the whole repo as "watched" in GitHub?
Reacted by Taine Zhao, Massimo Redaelli, Ilia Korvigo, William Harvey, Max Kühn, Sascha Desch, ksonj, Aly Cerruti, Poscat, daa and 383 more
Reacted by Felipe S. S. Schneider, Harald Husum, Randolf Scholz, Ellis Breen, Santiago Saavedra, milheht, Jonathan Plasse, Darkavid, Pragy Agarwal, Joren Hammudoglu and 12 more
Reacted by Taine Zhao, bwo, Rodrigo H. Mota, ksonj, 林煒清(Lin Wei-Ching), Aly Cerruti, Sune Debel, Pradeep Kumar, gsedometov, twosigmajab and 74 more
Reacted by Sunghyun Kim, Benoît Dubreuil, Justin Garcia, Las, Rory Hart, Felipe S. S. Schneider, Harald Husum, Lukas Kronsbein, Randolf Scholz, Byeonghoon Yoo and 23 more
Reacted by Connor Newton, Justin Garcia, Felipe S. S. Schneider, Alex Waygood, Harald Husum, Randolf Scholz, Riccardo Bergamaschi, milheht, Jonathan Plasse, Julian Fortune and 17 more

Activity

Next
  1. ilevkivskyi commented on Mar 30, 2018

    @ilevkivskyi
    ilevkivskyi
    on Mar 30, 2018
    Member
    More actions

    I think this came up few times in other discussions, for example one use case is python/mypy#4395. But TBH this is low priority, since such use cases are quite rare.

    Reacted by Anton Agestam, martín and Ashrith Sagar
    Reacted by Matthew Hoffman, Rogério Chaves, Yi Zhou, Rafal Wojdyla, Tamika Nomara, Winston H., kazmi, Romain Yon, Lorenzo, Ivan Klass and 85 more
    Reacted by Предраг Николић
  2. ilevkivskyi
    added
    postponed
    on Mar 30, 2018
  3. tek commented on Mar 30, 2018

    @tek
    tek
    on Mar 30, 2018
    Author
    More actions

    damn, I searched very thoroughly but did not find this one! 😄
    So, consider this my +1!

    Reacted by Taine Zhao, Daniel Davis, Felipe S. S. Schneider, Harald Husum, Redowan Delowar, lapraswastaken, Mi!, Nyuan Zhang, Danipulok, Eldar S and 53 more
  4. gvanrossum commented on Mar 31, 2018

    @gvanrossum
    gvanrossum
    on Mar 31, 2018 via email
    Member
    More actions
    Adding your +1 is all fine, but who's going to do the (probably pretty complicated) implementation work?
    Reacted by laike9m, Guilherme Caminha, Sebastian Wagner, Michael Panchenko, Danipulok, Jasha Sommer-Simpson, immanelg, Hash, Romir K, Winston H. and 9 more
  5. tek commented on Mar 31, 2018

    @tek
    tek
    on Mar 31, 2018
    Author
    More actions

    are you approving the feature?

  6. gvanrossum commented on Mar 31, 2018

    @gvanrossum
    gvanrossum
    on Mar 31, 2018 via email
    Member
    More actions
    I am neither approving nor disapproving. Just observing that it may be a lot of work for marginal benefits in most codebases.
  7. tek commented on Mar 31, 2018

    @tek
    tek
    on Mar 31, 2018
    Author
    More actions

    awfully pragmatic. Where's your sense of adventure? 😄
    anyways, I'll work on it, though it's gonna take a while to get into the project.

    Reacted by Landon Poch, Francisco Castro, Mike McDermott, Balázs Cene, Redowan Delowar, lapraswastaken, Jasha Sommer-Simpson, Ellis Breen, Paweł Rubin, benedikt-bartscher and 11 more
  8. landonpoch commented on Aug 14, 2018

    @landonpoch
    landonpoch
    on Aug 14, 2018
    More actions

    Similar to microsoft/TypeScript#1213

    Not sure if the discussion over there provides any useful insights to the effort over here.

    Reacted by Torsten Schmits, Mike McDermott, milheht, Díaz-Esparza and Alexander Schepanovski
  9. rcalsaverini commented on Jan 10, 2019

    @rcalsaverini
    rcalsaverini
    on Jan 10, 2019
    More actions

    Hi @tek. I'm also very interested in this, so I'd like to ask if you had any progress with this and volunteer to help if you want.

  10. tek commented on Jan 10, 2019

    @tek
    tek
    on Jan 10, 2019
    Author
    More actions

    @rcalsaverini sorry, I've been migrating my legacy code to haskell and am abandoning python altogether. but I wish you great success!

    Reacted by William Harvey, Profpatsch, Francisco Castro, hab, Mike McDermott, Dave Nicponski, Alexander Dmitriev, Balázs Cene, Harald Husum, Andrii Dmytruk and 15 more
    Reacted by Arseny Boykov, Ismail Bello, Feuermurmel, Shahriar Heidrich, Ilya Kamen, immanelg, Alexei Mochalov, Guillaume Desforges, Yann Hamdaoui, Lev Zlotnik and 15 more
    Reacted by Sunghyun Kim, Tin Tvrtković, Ellis Breen, London Lowmanstone and Axel PASCON
  11. rcalsaverini commented on Jan 10, 2019

    @rcalsaverini
    rcalsaverini
    on Jan 10, 2019
    More actions

    Oh, sad to hear but I see your point. Thanks.

  12. syastrov commented on Oct 10, 2019

    @syastrov
    syastrov
    on Oct 10, 2019
    More actions

    Just to add another use case (which I think relates to this issue):

    Using Literal types along with overloading __new__, along with higher-kinded typevars could allow implementing a generic "nullable" ORM Field class, using a descriptor to provide access to the appropriate nullable-or-not field values. The descriptor wouldn't have to be reimplemented in subclasses.

    It is one step closer to being possible due to the most recent mypy release's support for honoring the return type of __new__ (python/mypy#1020).

    Note: this is basically a stripped-down version of Django's Field class:

    # in stub file
    
    from typing import Generic, Optional, TypeVar, Union, overload, Type
    from typing_extensions import Literal
    
    _T = TypeVar("_T", bound="Field")
    _GT = TypeVar("_GT")
    
    class Field(Generic[_GT]):
        # on the line after the overload: error: Type variable "_T" used with arguments
        @overload
        def __new__(cls: Type[_T], null: Literal[False] = False, *args, **kwargs) -> _T[_GT]: ...
        @overload
        def __new__(cls: Type[_T], null: Literal[True], *args, **kwargs) -> _T[Optional[_GT]]: ...
        def __get__(self, instance, owner) -> _GT: ...
    
    class CharField(Field[str]): ...
    class IntegerField(Field[int]): ...
    # etc...
    
    # in code
    
    class User:
      f1 = CharField(null=False)
      f2 = CharField(null=True)
    
    reveal_type(User().f1) # Expected: str
    reveal_type(User().f2) # Expected: Union[str, None]
    Reacted by Samuel Colvin, Mike McDermott, Kuza, d-danilkin, Gleb Haranin, lapraswastaken, Théo, Serhii Tereshchenko, Albin Skott, benedikt-bartscher and 6 more
  13. samuelcolvin commented on Apr 26, 2020

    @samuelcolvin
    samuelcolvin
    on Apr 26, 2020
    Sponsor
    More actions

    I wonder if this is what I need or if there's currently a work around for my (slightly simpler) case?:

    I'm building an async redis client with proper type hints. I have a "Commands" class with methods for all redis commands (get, set, exists, strlen ... and hundreds more). Normally each of those methods should return a future (actually coroutine) to the result, but in pipeline mode they should all return None - the commands are added to the pipeline to be executed later.

    This is easy enough to implement in python, but not so easy to type hint correctly.

    Basic example:

    class Redis:
        def execute(self, command) -> Coroutine[Any, Any, Union[None, str, int, float]]:
            return self.connection.execute(...)
    
        def get(self, *args) -> Coroutine[Any, Any, str]:
            ...
            return self.execute(command)
    
        def set(self, *args) -> Coroutine[Any, Any, None]:
            ...
            return self.execute(command)
    
        def exists(self, *args) -> Coroutine[Any, Any, bool]:
            ...
            return self.execute(command)
    
        # ... and many MANY more ...
    
    
    class RedisPipeline(Redis):
        def execute(self, command) -> None:
            self.pipeline.append(command)

    I tried numerous options to make Coroutine[Any, Any, xxx] generic, but nothing seems to work.

    Is there any way around this with python 3.8 and latest mypy? If not a solution would be wonderful - as far as I can think, my only other route for proper types is a script which copy and pastes the entire class and changes the return types in code.

    Reacted by Mike McDermott, Redowan Delowar and chun1
  14. gvanrossum commented on Apr 26, 2020

    @gvanrossum
    gvanrossum
    on Apr 26, 2020
    Member
    More actions

    @samuelcolvin I don't think this question belongs in this issue. The reason for the failure (knowing nothing about Redis but going purely by the code you posted) is that in order to make this work, the base class needs to switch to an Optional result, i.e.

        def execute(self, command) -> Optional[Coroutine[Any, Any, Union[None, str, int, float]]]:
    
  15. samuelcolvin commented on Apr 26, 2020

    @samuelcolvin
    samuelcolvin
    on Apr 26, 2020
    Sponsor
    More actions

    I get that, but I need all the public methods to definitely return a coroutine. Otherwise, if it returned an optional coroutine, it would be extremely annoying to use.

    What I'm trying to do is modify the return type of many methods on the sub-classes, including "higher kind" types which are parameterised.

    Hence thinking it related to this issue.

  16. 213 remaining items

    Load more actions
  17. RobinSobczyk commented on May 28, 2026

    @RobinSobczyk
    RobinSobczyk
    on May 28, 2026
    More actions

    This also leads me to question the meaning of expressions like Concatenate[..., P]. More precisely, Concatenate seems to currently accept any number of Ellipsis and ParamSpecs, without any specified semantic. Am I missing an information there, or is it the currently desired behavior ?
    More specifically, from what I understand, Concatenate should be kinded as ...[Type] -> PackedDomain -> PackedDomain (with ...[K] representing a variadic number of elements of kind K), and this should forbid those previously questionned uses.

  18. RobinSobczyk commented on Jun 19, 2026

    @RobinSobczyk
    RobinSobczyk
    on Jun 19, 2026
    More actions

    Just a quick progress report, I'm splitting my PEP in 5 PEPs as it was getting really long due to a high number of things being required before properly defining higher kinded typevars. The PEPs will be as follow :
    9995 : Defining kinds for actual types (TypeVars would still only represent only concrete types at this level)
    9996 : Numerous extensions that naturally comes after defining kinds (like TypedDicts in Concatenate etc)
    9997 : Reworking the TypeVar substitution system (defining TypeTemplates etc)
    9998 : Adding Higher Kinded TypeVars with only basic features
    9999 : Adding advanced higher kinded features (@lift decorator etc)

    Again, no ETA, but I can give the current state of things :
    9995 : Implementation missing
    9996 : Incomplete, lot of things still missing (this is currently what I'm spending most of my time on)
    9997 : Specification almost complete, no implementation
    9998 : Most of rationale and specification is done, no implementation
    9999 : Mostly ideas for now, require more in depth work

    I plan on releasing 9995, 9996 and 9997 together at they feel quite connected to me. Then 9998, and finally 9999. Obviously will keep updating here sometimes (feel free to ping me if I don't give updates for too long).

    Reacted by Stephen Moore, Sebastian Wagner, djsigmann, Philipp A., niqzart, soufianeamini, Lorenzo, João Pedro, benedikt-bartscher and Ashrith Sagar
    Reacted by Sebastian Wagner, Jasper, João Pedro, Loïc Riegel, Ashrith Sagar and MaloL
  19. ringohoffman
    added 11 commits that reference this issue on Sep 19, 2026

    Flesh out DeviceTransferable HKT prototype with concrete Tensor imple…

    7b918ae

    Flesh out Django Field descriptor HKT prototype

    05d80dd

    Document container deconstruction in filter_and_count_dups HKT prototype

    2f6e5ed

    Flesh out frozendict.__new__ constructor HKT prototype

    7f18ec2

    Clean up Functor HKT prototype and add context header

    c020ce1

    Clean up Ext/Handler modify HKT prototype and add context header

    93f67a0

    Simplify generic class factory HKT prototype using Callable

    7bf1f02

    Flesh out MongoModel query prototype and clean up HKT error references

    a013b48

    Clean up SettingsRegistry classmethod HKT prototype and compare with …

    0c6f87e

    Flesh out toolz valmap HKT prototype and fix filename typo

    5cce0cf

    Add Trade cross-parameter constructor application HKT prototype

    d3e88c5
  20. RobinSobczyk commented on Sep 22, 2026

    @RobinSobczyk
    RobinSobczyk
    on Sep 22, 2026
    More actions

    Sorry for the long silence, I've been facing health problems in August and I'm still recovering, so I got really late in regards of where I wish I would have been currently. Obviously, health is my priority so project is on the back burner for now, but it's still in my plans, just extremely slowed down. I'm just really giving a sign of life here.

    Reacted by Jelle Zijlstra, Riccardo Bergamaschi, Anh71me, Harald Husum, Krzysztof Jagiello, Philipp A., Loïc Riegel, Jos Verlinde, Charles, niqzart and 8 more
  21. ringohoffman
    added a commit that references this issue on Oct 31, 2026

    Add python/typing#548 transcript and incremental updater

    8d303d7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: featureDiscussions about new features for Python's type annotationsDiscussions about new features for Python's type annotations

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.