Observed since 20 Oct, 19:55 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Algebraic Data Types via Class Decorators
This package provides a class decorator for defining
Algebraic Data Types (ADTs) as known from
Haskell (data),
OCaml (type), and
Rust (enum).
Simplicity. This package exports only a single definition: the
adt class decorator:
from adt import adt
Concision. Constructors are specified via class annotations,
allowing for syntax comparable to Rust's enums:
@adt
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
Pattern Matching via match is fully supported (Python >= 3.10):
event = Event.KeyPress(key='a', modifiers=['shift'])
match event:
case Event.MouseClick(x, y): print(f"Clicked at ({x}, {y}).")
case Event.KeyPress(key, mods): print(f"Pressed key {key}.")
Named and unnamed constructor fields are supported:
KeyPress, are specified as a dict[str, type];MouseClick, are specified as a list[type];type;Getters, Setters, and Instance-Checking methods are derived as an alternative to pattern matching, e.g.
if event.is_mouse_click():
print(f"Clicked at ({event._1}, {event._2}).")
elif event.is_key_press():
print(f"Pressed key {event.key}.")
Constructors are customizable dataclasses.
The dataclass
decorator derives many useful method implementations,
e.g. structural equality and string-conversion.
Additonal keyword arguments to adt are forwarded as keyword
arguments to the dataclass annotations of all constructors:
@adt(frozen=True) # <-- Use @dataclass(frozen=True) for all constructors.
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
event = Event.MouseClick(5, 10)
event._0 = 42 # Error! Constructor dataclass is frozen.
Constructors inherit from the decorated type. Making the constructors inherit from the decorated class, allows to define methods with pattern matching directly in the decorated class and call them on objects of the constructor classes:
@adt
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
def print(self):
match self:
case Event.MouseClick(x, y): print(f"Clicked at ({event._1}, {event._2}).")
case Event.KeyPress(key, mods): print(f"Pressed key {event.key}.")
Event.MouseClick(5, 10).print()
Constructors can be exported into the global namespace.
@adt(export=True) # <-- Makes `Event.` prefixes optional for constructors.
class Event:
MouseClick: [int, int]
KeyPress: {'key': str, 'modifiers': list[str]}
def print(self):
match self:
case MouseClick(x, y): ... # <-- As promised: no `Event.MouseClick`!
case KeyPress(key, mods): ... # <-- As promised: no `Event.KeyPress`!
Reflection.
The decorated class has a static field constructors: dict[str, type]
which maps the constructor names to their classes, e.g.
key_event = Event.constructors['KeyPress'](key='a', modifiers=['shift'])
The code generated in the above example by the adt decorator for the
Event ADT behaves equivalent to the following code, with the
exception that the constructor classes are constructed anonymously, so
the global namespace is not even temporarily polluted unless
@adt(export=True) is used.
from dataclasses import dataclass
class Event:
def __init__(self, *args, **kwargs):
raise TypeError(
"Tried to construct an ADT instead of one of it's constructors.")
def is_mouse_click(self) -> bool:
return isinstance(self, Event.MouseClick)
def is_key_press(self) -> bool:
return isinstance(self, Event.KeyPress)
@dataclass
class MouseClick(Event):
_1: int
_2: int
@dataclass
class KeyPress(Event):
key: str
modifiers: list[str]
Event.MouseClick = MouseClick
Event.KeyPress = KeyPress
if not export:
del MouseClick
del KeyPress
Event.constructors = {
'MouseClick': Event.MouseClick,
'KeyPress': Event.KeyPress,
}
The following compares this package to packages which aim to provide similar functionality:
algebraic-data-types
also describes ADTs via class decorators and
annotations, but does not support pattern matching via match, as it is aimed
at older python versions. Also the package does not support named
constructor parameters.
algebraic-data-type and
UxADT
does not support a concise definition via decorators and does not
support pattern matching via match.
choicetypes implements
similar functionality, but instead of having subclasses for the constructors,
the __init__-method of the main ADT-Class takes a named argument
for each constructor variant, which is more verbose, error-prone and
does not have a straightforward way to support named constructor arguments.
match-variant supports
pattern matching via match and realizes ADTs by inheriting from a
base class called Variant that seems to process the annotations.
It does not seem to support named constructor parameters and
methods that check if the ADT is a certain constructor.
py-foldadt comes without
any documentation and has unclear functionality. It defines various
algebraic structures like semirings with unclear connection to ADTs.
pypistats · 42 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-20 – 2026-10-20 | 2 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-19 – 2026-10-19 | 3 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-18 – 2026-10-18 | 3 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-16 – 2026-10-16 | 2 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-15 – 2026-10-15 | 5 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-14 – 2026-10-14 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-13 – 2026-10-13 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-12 – 2026-10-12 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-11 – 2026-10-11 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-10 – 2026-10-10 | 5 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-09 – 2026-10-09 | 8 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-08 – 2026-10-08 | 2 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-06 – 2026-10-06 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-03 – 2026-10-03 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-10-02 – 2026-10-02 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-30 – 2026-09-30 | 10 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-29 – 2026-09-29 | 2 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-28 – 2026-09-28 | 3 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-27 – 2026-09-27 | 4 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-26 – 2026-09-26 | 8 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-25 – 2026-09-25 | 3 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-24 – 2026-09-24 | 5 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-22 – 2026-09-22 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-15 – 2026-09-15 | 28 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-14 – 2026-09-14 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-12 – 2026-09-12 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-09 – 2026-09-09 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-08 – 2026-09-08 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-07 – 2026-09-07 | 3 | 2026-10-21T14:59:12.9799616Z |
| 2026-09-03 – 2026-09-03 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-31 – 2026-08-31 | 2 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-24 – 2026-08-24 | 2 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-20 – 2026-08-20 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-17 – 2026-08-17 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-14 – 2026-08-14 | 4 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-11 – 2026-08-11 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-09 – 2026-08-09 | 8 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-03 – 2026-08-03 | 3 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-02 – 2026-08-02 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-08-01 – 2026-08-01 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-07-24 – 2026-07-24 | 1 | 2026-10-21T14:59:12.9799616Z |
| 2026-07-23 – 2026-07-23 | 2 | 2026-10-21T14:59:12.9799616Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.2.11 | 25 Jul 2023 | 0 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 19:55 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:2a811c549ea74bc3dfb33d0ce208683069a2df051e543bfe2417f16341c8092e