11

Suppose I want to write a generic class using mypy, but the type argument for the class is itself a generic type. For example:

from typing import TypeVar, Generic, Callable

A = TypeVar("A")
B = TypeVar("B")
T = TypeVar("T")


class FunctorInstance(Generic[T]):
    def __init__(self, map: Callable[[Callable[[A], B], T[A]], T[B]]):
        self._map = map

    def map(self, x: T[A], f: Callable[[A], B]) -> T[B]:
        return self._map(f, x)

When I try to call mypy in the definition above I get an error:

$ mypy typeclasses.py 
typeclasses.py:9: error: Type variable "T" used with arguments
typeclasses.py:12: error: Type variable "T" used with arguments 

I tried adding constraints to the T TypeVar's definition but failed to make this work. Is it possible to do this?

martineau
  • 119,623
  • 25
  • 170
  • 301
Rafael S. Calsaverini
  • 13,582
  • 19
  • 75
  • 132

2 Answers2

5

Currently, as of writing, the mypy project does not support higher-kinded types. See the following github issue:

https://github.com/python/typing/issues/548

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
4

The returns package now provides some third party support for HKTs.

To copy a snippet from their docs

>>> from returns.primitives.hkt import Kind1
>>> from returns.interfaces.container import Container1
>>> from typing import TypeVar

>>> T = TypeVar('T', bound=Container1)

>>> def to_str(arg: Kind1[T, int]) -> Kind1[T, str]:
...   ...

Your Functor would be sth like

from typing import TypeVar, Generic, Callable

A = TypeVar("A")
B = TypeVar("B")
T = TypeVar("T")


class FunctorInstance(Generic[T]):
    def __init__(
        self, map: Callable[[Callable[[A], B], Kind1[T, A]], Kind1[T, B]]
    ):
        self._map = map

    def map(self, x: Kind1[T, A], f: Callable[[A], B]) -> Kind1[T, B]:
        return self._map(f, x)
joel
  • 6,359
  • 2
  • 30
  • 55