Enums and match
An enum lists the forms a value can take. Each variant may carry named fields:
enum Health: Ok Degraded(healthy: int, total: int) Down
let checks = [Ok, Degraded(2, 3), Down, Health.Degraded(healthy=0, total=1)]print(checks)print(Degraded(2, 3) == Degraded(2, 3))[Ok, Degraded(healthy=2, total=3), Down, Degraded(healthy=0, total=1)]TrueVariants are used by name, or qualified as Health.Ok when two enums share a variant name. Enums compare structurally, and their fields are reached through match. Enums can be generic: enum Result[T]: Success(value: T), Failure(message: str).
match picks the first arm whose pattern fits. There’s no case keyword: each arm is a pattern, a colon, and a statement or an indented block.
enum Health: Ok Degraded(healthy: int, total: int) Down
def describe(h: Health) -> str: match h: Ok: return "all good" Degraded(healthy, total) if healthy * 2 >= total: return f"mostly up ({healthy}/{total})" Degraded(_, total): return f"mostly down (of {total})" Down: return "down"
for h in [Ok, Degraded(2, 3), Degraded(1, 4), Down]: print(describe(h))all goodmostly up (2/3)mostly down (of 4)downExhaustiveness
Section titled “Exhaustiveness”A match must handle every value its subject can have. Leave one out and the compiler says which:
enum Health: Ok Degraded(healthy: int, total: int) Down
def describe(h: Health) -> str: match h: Ok: return "all good" Degraded(up, total): return f"{up}/{total}"main.tpn:7:5: error TP0204: non-exhaustive match (missing: Down)So when you add a variant, the compiler finds every match that needs a new arm. _ matches anything, for when you really mean “everything else”.
Patterns
Section titled “Patterns”Patterns nest, as in Python’s match:
| Pattern | Matches |
|---|---|
0, "api", True, 1.5, None |
a value equal to the literal |
x |
anything, binding it to x |
_ |
anything |
Degraded(h, t) |
a variant, with sub-patterns for its fields |
Point(x=0, y=y), Point(0, y) |
an instance of a class, with sub-patterns for its fields |
(a, b), [first, *rest] |
a tuple, or a list, by its elements |
{"name": n} |
a dict with those keys |
A | B |
either pattern |
p as name |
p, binding the whole value |
p if condition |
p, when the guard holds |
def classify(command: list[str]) -> str: match command: []: return "nothing" ["go", ("north" | "south") as direction]: return f"walk {direction}" ["take", item, *rest] if len(rest) == 0: return f"pick up {item}" [verb, *_]: return f"don't know how to {verb}"
let commands: list[list[str]] = [[], ["go", "north"], ["take", "lamp"], ["take", "a", "b"], ["dance"]]for c in commands: print(classify(c))nothingwalk northpick up lampdon't know how to takedon't know how to dancematch expressions
Section titled “match expressions”match is also an expression, whose arms are values. It’s Taipan’s conditional expression too:
enum Health: Ok Degraded(healthy: int, total: int) Down
let h = Degraded(1, 4)let label = match h: Ok: "up" Degraded(healthy, total): f"{healthy}/{total} up" Down: "down"print(label)
let n = 7let parity = match n % 2 == 0: True: "even" False: "odd"print(parity)1/4 upoddAn arm may also raise, as in _: raise ValueError("unknown").
Next: Errors.
© 2026 Discover Edge, LLC · Taipan is released under the MIT License.