Page MenuHomeSoftware Heritage
Paste P761

Python 3.10 Maybe
ActivePublic

Authored by vlorentz on Sep 13 2020, 2:48 PM.
import typing
from typing import *
@typing.sealed
class Maybe(Generic[T]):
"""An Option like it ought to be: an ADT, not like Python's Optional[T].
"""
# Ideally this would be named Option/None/Some for consistency with Rust,
# but it clashes with Python names, so this uses Haskell names instead.
__cache = {}
def __class_getitem__(cls, type_param):
"""Generates Just and Nothing variants for the non-generic class."""
if type_param in cls.__cache:
return cls.__cache[type_param]
new_cls = type(f"Maybe[{type_param}]", (cls,), {})
@dataclass
class Just(new_cls):
item: type_param
@classmethod
def from_ast(cls, ast):
return Just(type_param.from_ast(ast))
@dataclass
class Nothing(new_cls):
pass
new_cls.Just = Just
new_cls.Nothing = Nothing
cls.__cache[type_param] = new_cls
return new_cls
T = typing.TypeVar("T")
U = typing.TypeVar("U")
def map_maybe(m: Maybe[T], f: typing.Callable[[T], U]) -> Maybe[U]:
M = m.__class__
match m:
case M.Nothing():
return M.Nothing()
case M.Just(item):
return M.Just(f(item))
case _:
print("oops", repr(m))
print(map_maybe(Maybe[int].Nothing(), lambda x: x*2)) # Maybe.__class_getitem__.<locals>.Nothing()
print(map_maybe(Maybe[int].Just(21), lambda x: x*2)) # Maybe.__class_getitem__.<locals>.Just(item=42)

Event Timeline

vlorentz edited the content of this paste. (Show Details)