notes

Log | Files | Refs | README

mealy_and_moore_machine.md (7172B)


      1 # Mealy and Moore Machine
      2 
      3 # Compare Mealy and Moore state machines with Rust code
      4 
      5 The key difference between Mealy and Moore
      6 [state machines](/system_design/design_patterns/finite_state_machine.md) comes down to **where
      7 the output lives**: in Moore machines, output is tied to the _state_; in Mealy
      8 machines, output is tied to the _transition_ (state + input together).[^1]
      9 
     10 ---
     11 
     12 ## Moore Machine
     13 
     14 In a **Moore machine**, each state has a fixed output associated with it,
     15 regardless of how you arrived there or what the current input is. The output
     16 only changes when you _enter a new state_ — making it synchronous and immune to
     17 input glitches.[^2][^3]
     18 
     19 Here's a traffic light modelled as a Moore machine — the output (light colour)
     20 depends purely on the current state:
     21 
     22 ```rust
     23 #[derive(Debug, Clone, PartialEq)]
     24 enum TrafficState {
     25     Red,
     26     Green,
     27     Yellow,
     28 }
     29 
     30 #[derive(Debug)]
     31 enum Input {
     32     Timer,
     33 }
     34 
     35 struct MooreMachine {
     36     state: TrafficState,
     37 }
     38 
     39 impl MooreMachine {
     40     fn new() -> Self {
     41         MooreMachine { state: TrafficState::Red }
     42     }
     43 
     44     // Output is derived from STATE alone — no input needed
     45     fn output(&self) -> &str {
     46         match self.state {
     47             TrafficState::Red    => "STOP",
     48             TrafficState::Green  => "GO",
     49             TrafficState::Yellow => "SLOW DOWN",
     50         }
     51     }
     52 
     53     // Transition: input triggers state change, output follows state
     54     fn transition(&mut self, input: Input) {
     55         self.state = match (&self.state, input) {
     56             (TrafficState::Red,    Input::Timer) => TrafficState::Green,
     57             (TrafficState::Green,  Input::Timer) => TrafficState::Yellow,
     58             (TrafficState::Yellow, Input::Timer) => TrafficState::Red,
     59         };
     60         // Output is read AFTER the state changes
     61         println!("State: {:?} → Output: {}", self.state, self.output());
     62     }
     63 }
     64 
     65 fn main() {
     66     let mut fsm = MooreMachine::new();
     67     println!("Initial output: {}", fsm.output()); // "STOP"
     68     fsm.transition(Input::Timer); // Green → "GO"
     69     fsm.transition(Input::Timer); // Yellow → "SLOW DOWN"
     70     fsm.transition(Input::Timer); // Red → "STOP"
     71 }
     72 ```
     73 
     74 Output is produced **after** entering the new state — `output()` takes `&self`
     75 with no input parameter.[^3]
     76 
     77 ---
     78 
     79 ## Mealy Machine
     80 
     81 In a **Mealy machine**, output is produced **on the transition** — it depends on
     82 both the current state _and_ the input that triggered the move. This means
     83 outputs can react instantly to inputs, and you typically need fewer states than
     84 an equivalent Moore machine.[^4][^1]
     85 
     86 Here's a coin-operated vending machine where the output depends on both state
     87 and the coin inserted:
     88 
     89 ```rust
     90 #[derive(Debug, Clone, PartialEq)]
     91 enum VendingState {
     92     Idle,
     93     Has10p,
     94     Has20p,
     95 }
     96 
     97 #[derive(Debug)]
     98 enum Coin {
     99     P10,
    100     P20,
    101 }
    102 
    103 // Output is produced ON the transition, not from the state alone
    104 #[derive(Debug)]
    105 enum Output {
    106     None,
    107     Dispense(&'static str),
    108     ReturnChange(u32),
    109 }
    110 
    111 struct MealyMachine {
    112     state: VendingState,
    113 }
    114 
    115 impl MealyMachine {
    116     fn new() -> Self {
    117         MealyMachine { state: VendingState::Idle }
    118     }
    119 
    120     // Returns (new_state, output) — output depends on BOTH state AND input
    121     fn transition(&mut self, coin: Coin) -> Output {
    122         let (next_state, output) = match (&self.state, coin) {
    123             (VendingState::Idle,  Coin::P10) => (VendingState::Has10p, Output::None),
    124             (VendingState::Idle,  Coin::P20) => (VendingState::Has20p, Output::None),
    125             (VendingState::Has10p, Coin::P10) => (VendingState::Has20p, Output::None),
    126             (VendingState::Has10p, Coin::P20) => (VendingState::Idle,   Output::Dispense("Chewing gum (30p)")),
    127             (VendingState::Has20p, Coin::P10) => (VendingState::Idle,   Output::Dispense("Chocolate (30p)")),
    128             (VendingState::Has20p, Coin::P20) => (VendingState::Idle,   Output::ReturnChange(10)),
    129         };
    130         self.state = next_state;
    131         output
    132     }
    133 }
    134 
    135 fn main() {
    136     let mut fsm = MealyMachine::new();
    137     println!("{:?}", fsm.transition(Coin::P10)); // None
    138     println!("{:?}", fsm.transition(Coin::P20)); // Dispense("Chewing gum (30p)")
    139     println!("{:?}", fsm.transition(Coin::P20)); // None
    140     println!("{:?}", fsm.transition(Coin::P10)); // Dispense("Chocolate (30p)")
    141 }
    142 ```
    143 
    144 Notice `transition()` takes **both** `&self` and `coin` to compute the output —
    145 a dead giveaway of the Mealy model.[^5]
    146 
    147 ---
    148 
    149 ## Side-by-Side Comparison
    150 
    151 | Feature                      | Moore                                    | Mealy                                       |
    152 | :--------------------------- | :--------------------------------------- | :------------------------------------------ |
    153 | **Output depends on**        | Current state only                       | Current state + input                       |
    154 | **Output location**          | Attached to state                        | Attached to transition                      |
    155 | **Rust signature**           | `fn output(&self)`                       | `fn transition(&mut self, input) -> Output` |
    156 | **Number of states**         | More (one per output combo)              | Fewer [^4]                                  |
    157 | **Output timing**            | After state change (synchronous)         | Immediately on input (asynchronous) [^2]    |
    158 | **Input glitch sensitivity** | Immune                                   | More sensitive [^2]                         |
    159 | **Best for**                 | Display/status outputs, digital circuits | Reactive systems, protocol parsers          |
    160 
    161 ---
    162 
    163 ## Key Takeaway
    164 
    165 Both models are equally expressive — any Mealy machine can be converted to a
    166 Moore machine by splitting states, and vice versa. In Rust, the distinction maps
    167 cleanly: Moore output lives in a method that reads `&self` alone, while Mealy
    168 output is returned from the transition method that takes both `&self` and the
    169 input event.[^6][^5]
    170 <span style="display:none">[^10][^11][^12][^13][^14][^15][^7][^8][^9]</span>
    171 
    172 <div align="center">⁂</div>
    173 
    174 [^1]: https://www.geeksforgeeks.org/theory-of-computation/difference-between-mealy-machine-and-moore-machine/
    175 
    176 [^2]: https://www.youtube.com/watch?v=YiQxeuB56i0
    177 
    178 [^3]: https://stackoverflow.com/questions/4009283/mealy-v-s-moore
    179 
    180 [^4]: https://mil.ufl.edu/3701/classes/joel/16 Lecture.pdf
    181 
    182 [^5]: https://comp.lang.forth.narkive.com/zJDmPu3N/mealy-vs-moore-fsm
    183 
    184 [^6]: https://www.reddit.com/r/explainlikeimfive/comments/30uq6e/eli5_the_difference_between_a_mealey_machine_and/
    185 
    186 [^7]: https://www.youtube.com/watch?v=kb-Ww8HaHuE
    187 
    188 [^8]: https://forum.allaboutcircuits.com/threads/when-to-use-mealy-machine-and-when-to-use-moore-machine.190031/
    189 
    190 [^9]: https://github.com/rust-cy/generic-state-machine-rs
    191 
    192 [^10]: https://docs.rs/rust-fsm/
    193 
    194 [^11]: https://users.rust-lang.org/t/how-to-create-complex-state-machines/82714
    195 
    196 [^12]: https://www.reddit.com/r/FPGA/comments/vmlb5z/is_there_any_difference_in_my_implementation_of/
    197 
    198 [^13]: https://oneuptime.com/blog/post/2026-02-01-rust-state-machines/view
    199 
    200 [^14]: https://lib.rs/crates/edfsm
    201 
    202 [^15]: https://blog.devgenius.io/building-robust-distributed-state-machines-in-rust-a-comprehensive-guide-ad1a358134df