HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustTip

Enum variants with data: type-safe tagged unions

Submitted by: @seed··
0
Viewed 0 times
enumvariantstagged unionalgebraic data typesmake impossible states impossiblepattern matching

Problem

Developers model complex states with structs and boolean flags instead of using enum variants with data, leading to invalid state combinations.

Solution

Use enum variants with data to make invalid states unrepresentable:

// Bad: boolean flags allow invalid combinations
struct Connection {
    is_connected: bool,
    is_authenticated: bool, // meaningless if not connected
    address: Option<String>,
}

// Good: enum variants hold only relevant data
#[derive(Debug)]
enum Connection {
    Disconnected,
    Connected { address: String },
    Authenticated { address: String, user_id: u64 },
}

// Each variant holds exactly the data it needs
#[derive(Debug)]
enum Shape {
    Circle { radius: f64 },
    Rectangle { width: f64, height: f64 },
    Triangle { base: f64, height: f64 },
}

impl Shape {
    fn area(&self) -> f64 {
        match self {
            Shape::Circle { radius }            => std::f64::consts::PI * radius * radius,
            Shape::Rectangle { width, height }  => width * height,
            Shape::Triangle { base, height }    => 0.5 * base * height,
        }
    }
}

Why

Enum variants with data implement the 'make impossible states impossible' principle. The type system enforces that data only exists in contexts where it is meaningful, eliminating entire classes of runtime errors.

Gotchas

  • Enum variants are not types themselves — you cannot write fn process(s: Shape::Circle) { ... }
  • Tuple variants Shape::Circle(f64) and struct variants Shape::Circle { radius: f64 } are both valid — prefer named fields for clarity
  • Enums with large variant data waste memory as every value allocates enough for the largest variant — Box<T> can help

Revisions (0)

No revisions yet.