Type State Pattern powered by Enum options?

Can Rust language be modified to have this syntax correct?

enum LampStates {
    On,
    Off
}

struct Lamp<State = LampStates> {
    state: State
}

impl Lamp<LampStates::Off> {
    fn on() -> Lamp<LampStates::On> {
        Self {
            state: LampStates::On
        }
    }
}

impl Lamp<LampStates::On> {
    fn off() -> Lamp<LampStates::Off> {
        Self {
            state: LampStates::Off
        }
    }
}

You can hide states in scope, yes, but this syntax looks good to be available for users, without tricky scope approach.

1 Like

Something similar to this would probably be possible once we have full support for const generics. You can already do something like this with the existing const generics:

#[derive(Debug)]
struct Lamp<const STATE: bool> {
    state: bool
}

impl Lamp<false> {
    fn on(self) -> Lamp<true> {
        Lamp::<true> { state: true }
    }
}

impl Lamp<true> {
    fn off(self) -> Lamp<false> {
        Lamp::<false> { state: false }
    }
}

fn main() {
    let lamp = Lamp::<false> { state: false };
    dbg!(&lamp);
    let lamp = lamp.on();
    dbg!(&lamp);
    let lamp = lamp.off();
    dbg!(&lamp);

    // Doesn't compile
    //let lamp = lamp.off();
}

You can presumably do something similar at the type level with trait bounds?

struct Lamp<State: LampState> { .. }

struct LampOn;

impl LampState for LampOn {}

struct LampOff;

impl LampState for LampOff {}

trait LampState: Sealed {}

trait Sealed {}
1 Like

Wouldn't this be ambiguous? At the moment struct Lamp<State = LampStates> means Lamp has a generic param that defaults to LampStates.

You may want to check adt_const_params - The Rust Unstable Book

2 Likes