use mindset::state_enum;
state_enum! {
enum OrderState {
Draft,
Submitted,
Processing,
Completed,
}
final: [Completed]
}
trait PaymentProcessor {
fn charge(&mut self, amount: f64) -> Result<(), String>;
}
trait Logger {
fn log(&mut self, message: &str);
}
struct Order {
id: u64,
total: f64,
}
fn can_submit(order: &Order) -> bool {
order.total > 0.0
}
fn submit_order<Env>(order: &mut Order, env: &mut Env) -> Result<(), String>
where
Env: PaymentProcessor + Logger,
{
env.log(&format!("Submitting order {}", order.id));
env.charge(order.total)?;
env.log(&format!("Order {} submitted successfully", order.id));
Ok(())
}
struct ProductionEnv;
impl PaymentProcessor for ProductionEnv {
fn charge(&mut self, amount: f64) -> Result<(), String> {
println!(" [Payment] Charging ${:.2}", amount);
Ok(())
}
}
impl Logger for ProductionEnv {
fn log(&mut self, message: &str) {
println!(" [Log] {}", message);
}
}
fn main() {
println!("=== Effectful State Machine Example ===\n");
let mut order = Order {
id: 42,
total: 99.99,
};
let mut env = ProductionEnv;
println!("Checking if order can be submitted...");
if can_submit(&order) {
println!(" Guard passed: Order total is positive\n");
println!("Executing submission with effects:");
match submit_order(&mut order, &mut env) {
Ok(_) => println!("\n Success!\n"),
Err(e) => println!("\n Error: {}\n", e),
}
} else {
println!(" Guard failed: Order total must be positive\n");
}
println!("Key Takeaways:");
println!("- Guards (can_submit) are pure functions with no side effects");
println!("- Actions (submit_order) are explicit about their effects via environment");
println!("- Environment traits enable testing with mocks");
println!("- Type system enforces separation of concerns");
println!("\n=== Example Complete ===");
}