effect-rs 0.1.0

A high-performance, strictly-typed, functional effect system for Rust.
Documentation
use effect_rs::{Cause, Effect, Exit, Runtime};
use std::sync::{Arc, Mutex};

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

    let program: Effect<(), (), i32> = Effect::succeed(10)
        .map(|x: i32| x * 2)
        .flat_map(|x| Effect::succeed(x + 5));

    let result = rt.block_on(program, ());

    match result {
        Exit::Success(val) => assert_eq!(val, 25),
        Exit::Failure(_) => panic!("Expected success"),
    }
}

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

    let program: Effect<(), &'static str, i32> = Effect::fail("error").map(|x: i32| x * 2);

    let result = rt.block_on(program, ());

    match result {
        Exit::Success(_) => panic!("Expected failure"),
        Exit::Failure(cause) => match cause {
            Cause::Fail(e) => assert_eq!(e, "error"),
            _ => panic!("Expected Fail cause"),
        },
    }
}

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

    let program: Effect<(), (), i32> = Effect::async_effect(|| async {
        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
        42
    });

    let result = rt.block_on(program, ());

    match result {
        Exit::Success(val) => assert_eq!(val, 42),
        Exit::Failure(_) => panic!("Expected success"),
    }
}

#[test]
fn test_acquire_release() {
    let rt = Runtime::new();
    let released = Arc::new(Mutex::new(false));
    let released_clone = released.clone();

    let program: Effect<(), (), i32> = Effect::acquire_release(Effect::succeed(10), move |_, _| {
        let released = released_clone.clone();
        Effect::<(), (), ()>::async_effect(move || async move {
            let mut guard = released.lock().unwrap();
            *guard = true;
        })
    });

    let result = rt.block_on(program, ());

    match result {
        Exit::Success(val) => assert_eq!(val, 10),
        Exit::Failure(_) => panic!("Expected success"),
    }

    assert!(*released.lock().unwrap(), "Finalizer did not run");
}