effect-rs 0.1.0

A high-performance, strictly-typed, functional effect system for Rust.
Documentation
use effect_rs::{Effect, Exit, Runtime, STM, TRef};
use tokio::time::Duration;

#[test]
fn test_stm_commit() {
    let rt = Runtime::new();

    let tref = TRef::new(0);
    let tref_clone = tref.clone(); // Clone for transaction

    // Transaction: get + 1 -> set
    let transaction = tref_clone.get().flat_map(move |v| tref_clone.set(v + 1));

    let program = transaction.commit();

    let res = rt.block_on(program, ());
    match res {
        Exit::Success(_) => {}
        Exit::Failure(_) => panic!("STM Commit Failed"),
    }

    // Verify value
    let check = tref.get().commit();
    let val = rt.block_on(check, ());
    match val {
        Exit::Success(v) => assert_eq!(v, 1),
        Exit::Failure(_) => panic!("Read failed"),
    }
}

#[test]
fn test_stm_isolation() {
    // This is hard to test deterministically without manual interleaving or lots of iterations.
    // Let's rely on basic logic for now.
}

#[test]
fn test_stm_retry() {
    let rt = Runtime::new();
    let tref = TRef::new(0);

    // Fiber 1: Wait until TRef > 0
    let wait_program = tref
        .get()
        .flat_map(|v| if v > 0 { STM::succeed(v) } else { STM::retry() })
        .commit();

    // Fiber 2: Sleep then Set 1
    let tref_clone = tref.clone();
    let setter = Effect::<(), (), ()>::sleep(Duration::from_millis(50))
        .flat_map(move |_| tref_clone.set(1).commit());

    // Run parallel
    let program = wait_program.zip_par(setter);

    let result = rt.block_on(program, ());
    match result {
        Exit::Success((val, _)) => assert_eq!(val, 1),
        Exit::Failure(cause) => panic!("STM Failed: {:?}", cause),
    }
}