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