Light-weight algebraic effect (algebraic goroutine) in Rust.
Using go! macro just as Haskell's do notation while we use algebraic effects
instead of monads to avoid monad's composition issue.
Only one-shot (linear) algebraic effect based on coroutine is supported.
Therefore we need nightly compiler to transform code.
go!macro to run effects and coroutines, just like?and.await.Coroutine.mapto map results.Coroutine.and_thento chain operations.
Currently handlers can only be built by hand. There's no easy way to combine.
let prepare = #[coroutine] |_: Option<i32>| {
go!(Log("preparing".into()) => Effect);
return ResultCode(0);
};
let logic = #[coroutine] |_: Option<i32>| {
go!(Log("start".into()) => Effect); // inject Log into Effect type
go!(State::Set(Some(9)));
let s = go!(State::Get);
go!(Log(format!("Got {:?}", s)));
let res = go!(prepare, None);
if !res.is_ok() {
go!(Log(format!("error code: {}", res.0)));
}
return res;
};
// Now we can use different ways to interpret `Log` and `State` effects!
let mut handler: Handler<Option<i32>> = Handler::new();
let ans = handler.handle(None, logic);
dbg!(ans);To inject effects, we don't use coproduct, just From!
See examples/logging_and_states for details.
let div = #[coroutine]
|(a, b): (i32, i32)| {
if b == 0 {
go!(Exception::Raise("divided by 0".into()) => Exception);
}
return a / b;
};
let logic = #[coroutine]
|_: Context| {
println!("Start!");
let ans = go!(div, (4, 0) => Exception); // will stop executing rest continuation
println!("div result: {}", ans);
println!("end.");
return 0;
};
let mut handler = ExceptionHandler::new();
let ans = handler.handle(Context::None, logic);
dbg!(ans);See examples/exception for details.
let logic = #[coroutine]
|| {
println!("begin...");
println!("first let's wait for 3 secs...");
go!(Timeout::of(time::Duration::from_secs(3)) => Effect);
println!("next we try to wait 5 secs...");
go!(Timeout::of(time::Duration::from_secs(5)));
println!("end.");
};See examples/event_loop for details.
goroutineandgosyntax is cool (but golang's type system is terrible)algebraic effectis coolalgebraic goroutine (algoroutine)is probably bad ;)
- Macros for declare effect types
- More auto-injective traits
- Remove boxes for better performance