Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Higher Kinded Types in Python
import abc
import dataclasses
from typing import Callable, Generic, TypeVar
# TODO: pip install returns
# TODO: add `returns.contrib.mypy.returns_plugin` to mypy plugins
# TODO: read the docs at https://github.com/dry-python/returns
from returns.primitives.hkt import Kind1, SupportsKind1, kinded
_ValueType = TypeVar('_ValueType')
_NewValueType = TypeVar('_NewValueType')
_InstanceKind = TypeVar('_InstanceKind', bound='HasValue')
class HasValue(Generic[_ValueType]):
@abc.abstractmethod
@property
def value(self) -> _ValueType:
"""Returns a value property."""
@abc.abstractmethod
def with_value(
self: _InstanceKind,
new_value: _NewValueType,
) -> Kind1[_InstanceKind, _NewValueType]:
"""Creates a new instance with a changed value."""
@dataclasses.dataclass
class Box(SupportsKind1['Box', _ValueType], HasValue[_ValueType]):
value: _ValueType
length: int
width: int
height: int
def with_value(self, new_value: _NewValueType) -> 'Box[_NewValueType]':
return Box(new_value, self.length, self.width, self.height)
@dataclasses.dataclass
class Bag(SupportsKind1['Bag', _ValueType], HasValue[_ValueType]):
value: _ValueType
brand: str
model: str
def with_value(self, new_value: _NewValueType) -> 'Bag[_NewValueType]':
return Bag(new_value, self.brand, self.model)
@kinded
def apply_function(
instance: Kind1[_InstanceKind, _ValueType],
callback: Callable[[_ValueType], _NewValueType],
) -> Kind1[_InstanceKind, _NewValueType]:
new_value = callback(instance.value)
return instance.with_value(new_value)
box = Box(value=10, length=1, width=2, height=3)
bag = Bag(value=5, brand='Fancy', model='Baggy')
reveal_type(apply_function(box, str))
reveal_type(apply_function(bag, str))
# ex.py:58: note: Revealed type is 'ex.Box[builtins.str]'
# ex.py:59: note: Revealed type is 'ex.Bag[builtins.str]'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.