Skip to content

Instantly share code, notes, and snippets.

@aarondewindt
Last active July 4, 2025 20:29
Show Gist options
  • Save aarondewindt/1cb0af45f05c0da03bfbec6f050f5b58 to your computer and use it in GitHub Desktop.
Save aarondewindt/1cb0af45f05c0da03bfbec6f050f5b58 to your computer and use it in GitHub Desktop.

Revisions

  1. aarondewindt revised this gist Oct 11, 2021. 1 changed file with 4 additions and 8 deletions.
    12 changes: 4 additions & 8 deletions adt_demo_2.py
    Original file line number Diff line number Diff line change
    @@ -13,16 +13,12 @@ class UserInput(metaclass=ADTMeta):
    Nil: ...
    KeyPress: str
    KeyRelease: str

    class MouseClick:
    button: MouseButton
    x: int
    y: int
    MouseClick: tuple[MouseButton, int, int]


    def get_user_input() -> UserInput:
    # You play around with this return value.
    return UserInput.MouseClick(MouseButton.Middle, 42, 24)
    return UserInput.MouseClick((MouseButton.Middle, 42, 24))


    match get_user_input():
    @@ -35,8 +31,8 @@ def get_user_input() -> UserInput:
    case UserInput.KeyRelease(key):
    print(f"Key {key} was released")

    case UserInput.MouseClick(MouseButton.Middle, x, y):
    case UserInput.MouseClick((MouseButton.Middle, x, y)):
    print(f"The middle mouse button was clicked at ({x}, {y})")

    case UserInput.MouseClick(button, x, y):
    case UserInput.MouseClick((button, x, y)):
    print(f"Mouse clicked ({button}, {x}, {y})")
  2. aarondewindt revised this gist Oct 11, 2021. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions adt_demo_2.py
    Original file line number Diff line number Diff line change
    @@ -3,9 +3,9 @@

    # As simple Enum
    class MouseButton(metaclass=ADTMeta):
    left: ...
    middle: ...
    right: ...
    Left: ...
    Middle: ...
    Right: ...


    # As enum with parameters
    @@ -22,7 +22,7 @@ class MouseClick:

    def get_user_input() -> UserInput:
    # You play around with this return value.
    return UserInput.MouseClick(MouseButton.middle, 42, 24)
    return UserInput.MouseClick(MouseButton.Middle, 42, 24)


    match get_user_input():
    @@ -35,7 +35,7 @@ def get_user_input() -> UserInput:
    case UserInput.KeyRelease(key):
    print(f"Key {key} was released")

    case UserInput.MouseClick(MouseButton.middle, x, y):
    case UserInput.MouseClick(MouseButton.Middle, x, y):
    print(f"The middle mouse button was clicked at ({x}, {y})")

    case UserInput.MouseClick(button, x, y):
  3. aarondewindt revised this gist Oct 11, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion adt_demo_2.py
    Original file line number Diff line number Diff line change
    @@ -35,7 +35,7 @@ def get_user_input() -> UserInput:
    case UserInput.KeyRelease(key):
    print(f"Key {key} was released")

    case UserInput.MouseClick(button=MouseButton.middle, x=x, y=y):
    case UserInput.MouseClick(MouseButton.middle, x, y):
    print(f"The middle mouse button was clicked at ({x}, {y})")

    case UserInput.MouseClick(button, x, y):
  4. aarondewindt revised this gist Oct 11, 2021. 1 changed file with 42 additions and 0 deletions.
    42 changes: 42 additions & 0 deletions adt_demo_2.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    from adt import ADTMeta


    # As simple Enum
    class MouseButton(metaclass=ADTMeta):
    left: ...
    middle: ...
    right: ...


    # As enum with parameters
    class UserInput(metaclass=ADTMeta):
    Nil: ...
    KeyPress: str
    KeyRelease: str

    class MouseClick:
    button: MouseButton
    x: int
    y: int


    def get_user_input() -> UserInput:
    # You play around with this return value.
    return UserInput.MouseClick(MouseButton.middle, 42, 24)


    match get_user_input():
    case UserInput.Nil:
    print("No input")

    case UserInput.KeyPress(key):
    print(f"Key {key} was pressed")

    case UserInput.KeyRelease(key):
    print(f"Key {key} was released")

    case UserInput.MouseClick(button=MouseButton.middle, x=x, y=y):
    print(f"The middle mouse button was clicked at ({x}, {y})")

    case UserInput.MouseClick(button, x, y):
    print(f"Mouse clicked ({button}, {x}, {y})")
  5. aarondewindt revised this gist Oct 11, 2021. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions adt_demo.py
    Original file line number Diff line number Diff line change
    @@ -29,13 +29,18 @@ class d:
    match value:
    case Foo.a():
    print("Matched Foo.a")

    case Foo.b((val_int_1, val_str, 42)):
    print(f"Matched Foo.b with {val_int_1} {val_str} and the answer of life, the universe and everything")

    case Foo.b((val_int_1, val_str, val_int_2)):
    print(f"Matched Foo.b with {val_int_1} {val_str} {val_int_2}")

    case Foo.c(val_str):
    print(f"Matched Foo.c with {val_str}")

    case Foo.d("positional", val_int, (f1, f2)):
    print(f"Matched d with positional pattern db={val_int} dc=({f1}, {f2})")

    case Foo.d(da=val_str, db=val_int, dc=(f1, f2)):
    print(f"Matched d with da={val_str} db={val_int} dc=({f1}, {f2})")
  6. aarondewindt revised this gist Oct 11, 2021. 2 changed files with 3 additions and 13 deletions.
    9 changes: 0 additions & 9 deletions adt.py
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@
    import unittest
    from dataclasses import dataclass


    @@ -40,11 +39,3 @@ def create_init(klass, annotation):
    def __init__(self: klass, value: annotation) -> None:
    self.value = value
    return __init__


    class ADT(metaclass=ADTMeta):
    pass


    if __name__ == '__main__':
    unittest.main()
    7 changes: 3 additions & 4 deletions adt_demo.py
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    from adt import ADT
    from adt import ADTMeta


    class Foo(ADT):
    class Foo(metaclass=ADTMeta):
    a: ...
    b: tuple[int, str, int]
    c: str
    @@ -25,7 +25,6 @@ class d:
    # value = Foo.d("Baz", 69, (1.2, 3.5))
    # value = Foo.d("positional", 69, (1.2, 3.5))

    assert isinstance(value, Foo)

    match value:
    case Foo.a():
    @@ -39,4 +38,4 @@ class d:
    case Foo.d("positional", val_int, (f1, f2)):
    print(f"Matched d with positional pattern db={val_int} dc=({f1}, {f2})")
    case Foo.d(da=val_str, db=val_int, dc=(f1, f2)):
    print(f"Matched d with da={val_str} db={val_int} dc=({f1}, {f2})")
    print(f"Matched d with da={val_str} db={val_int} dc=({f1}, {f2})")
  7. aarondewindt created this gist Oct 11, 2021.
    50 changes: 50 additions & 0 deletions adt.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,50 @@
    import unittest
    from dataclasses import dataclass


    class ADTMeta(type):
    def __new__(mcs, name, bases, namespace: dict):
    adtc_class = super().__new__(mcs, name, bases, namespace)
    if "__is_adt_variant__" in namespace:
    if namespace["__is_adt_variant__"]:
    return adtc_class

    for member_name, member in namespace.items():
    if isinstance(member, type):
    variant_class = dataclass(type(member_name, (adtc_class,), {
    "__qualname__": f"{adtc_class.__qualname__}.{member_name}",
    "__is_adt_variant__": True,
    "__annotations__": member.__annotations__
    }))
    setattr(adtc_class, member_name, variant_class)

    annotations = namespace.pop("__annotations__", {})
    for variant_name, variant_annotation in annotations.items():
    variant_class = type(variant_name, (adtc_class,), {
    "__qualname__": f"{adtc_class.__qualname__}.{variant_name}",
    "__is_adt_variant__": True
    })

    if (variant_annotation is Ellipsis) or (variant_annotation is None):
    variant_class.__repr__ = lambda self: f"<{self.__class__.__qualname__}>"
    else:
    variant_class.__init__ = create_init(variant_class, variant_annotation)
    variant_class.__repr__ = lambda self: f"<{self.__class__.__qualname__} {repr(self.value)}>"
    variant_class.__match_args__ = ("value",)
    setattr(adtc_class, variant_name, variant_class)

    return adtc_class


    def create_init(klass, annotation):
    def __init__(self: klass, value: annotation) -> None:
    self.value = value
    return __init__


    class ADT(metaclass=ADTMeta):
    pass


    if __name__ == '__main__':
    unittest.main()
    42 changes: 42 additions & 0 deletions adt_demo.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,42 @@
    from adt import ADT


    class Foo(ADT):
    a: ...
    b: tuple[int, str, int]
    c: str

    class d:
    da: str
    db: int
    dc: tuple[float, float]


    assert issubclass(Foo.a, Foo)
    assert issubclass(Foo.b, Foo)
    assert issubclass(Foo.c, Foo)
    assert issubclass(Foo.d, Foo)


    value = Foo.a()
    value = Foo.b((1, "Hello", 1234))
    value = Foo.b((1, "World", 42))
    # value = Foo.c("Bar")
    # value = Foo.d("Baz", 69, (1.2, 3.5))
    # value = Foo.d("positional", 69, (1.2, 3.5))

    assert isinstance(value, Foo)

    match value:
    case Foo.a():
    print("Matched Foo.a")
    case Foo.b((val_int_1, val_str, 42)):
    print(f"Matched Foo.b with {val_int_1} {val_str} and the answer of life, the universe and everything")
    case Foo.b((val_int_1, val_str, val_int_2)):
    print(f"Matched Foo.b with {val_int_1} {val_str} {val_int_2}")
    case Foo.c(val_str):
    print(f"Matched Foo.c with {val_str}")
    case Foo.d("positional", val_int, (f1, f2)):
    print(f"Matched d with positional pattern db={val_int} dc=({f1}, {f2})")
    case Foo.d(da=val_str, db=val_int, dc=(f1, f2)):
    print(f"Matched d with da={val_str} db={val_int} dc=({f1}, {f2})")