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