Skip to content

Instantly share code, notes, and snippets.

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
from import Kind1, SupportsKind1, kinded
_ValueType = TypeVar('_ValueType')
_NewValueType = TypeVar('_NewValueType')
_InstanceKind = TypeVar('_InstanceKind', bound='HasValue')
class HasValue(Generic[_ValueType]):
def value(self) -> _ValueType:
"""Returns a value property."""
def with_value(
self: _InstanceKind,
new_value: _NewValueType,
) -> Kind1[_InstanceKind, _NewValueType]:
"""Creates a new instance with a changed value."""
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)
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)
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))
# note: Revealed type is 'ex.Box[builtins.str]'
# 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