use monadify::identity::{Identity, IdentityKind};
use monadify::mdo;
use monadify::transformers::writer::{Writer, WriterTKind};
type Logged<A> = Writer<Vec<String>, A>;
type WKind = WriterTKind<Vec<String>, IdentityKind>;
fn step(s: &str) -> Logged<()> {
WKind::tell(vec![s.to_string()])
}
fn pipeline() -> Logged<u64> {
mdo! {
WKind;
_ <- step("validate: order #42 ok");
_ <- step("charge: $100 captured");
_ <- step("ship: order #42 dispatched");
pure(100u64)
}
}
fn main() {
println!("=== Do-notation with WriterT: Order/Payment Audit Log ===\n");
println!("Test 1: run_writer_t — value and full audit trail");
let Identity((value, trail)) = pipeline().run_writer_t;
assert_eq!(value, 100u64, "captured amount must be 100");
assert_eq!(
trail,
vec![
"validate: order #42 ok".to_string(),
"charge: $100 captured".to_string(),
"ship: order #42 dispatched".to_string(),
],
"audit trail must contain exactly the three ordered entries"
);
println!(" Value (captured amount): {}", value);
println!(" Audit trail:");
for (i, entry) in trail.iter().enumerate() {
println!(" [{}] {}", i + 1, entry);
}
println!(" PASSED\n");
println!("Test 2: eval_writer_t — value only");
let Identity(v) = pipeline().eval_writer_t();
assert_eq!(v, 100, "eval_writer_t must return the captured amount 100");
println!(" eval_writer_t -> {}", v);
println!(" PASSED\n");
println!("Test 3: exec_writer_t — audit log only");
let Identity(log) = pipeline().exec_writer_t();
assert_eq!(
log.len(),
3,
"exec_writer_t must return exactly 3 audit entries"
);
println!(" exec_writer_t -> {} entries", log.len());
for entry in &log {
println!(" - {}", entry);
}
println!(" PASSED\n");
println!("=== All tests passed! ===");
println!("\nKey insight: `mdo!` with `WriterT` accumulates the audit trail implicitly:");
println!(" * `tell` appends one log entry and yields unit.");
println!(" * `bind` sequences steps and combines their logs monoidally.");
println!(" * `run_writer_t` is a field exposing `Identity<(value, log)>` directly.");
println!(" * `eval_writer_t` projects the produced value (log discarded).");
println!(" * `exec_writer_t` projects the accumulated log (value discarded).");
println!(" * No log vector is ever threaded through any function argument.");
}