Handlers
A Handler is an effect transformation function of type impl Handler<'f, R, S, U, V>
(see the Handler
trait in fx-rs).
Handlers can change effect requirements, typically reducing them, but may also introduce new requirements or change the result type.
Handling an Effect
Let's rewrite the "length of string" function as a handler in Rust:
#![allow(unused)] fn main() { use fx::Fx; use fx::Handler; // Type alias for handler effect type RWHandler = Fx<Env, Output>; // Handler that takes Fx<(LenFn, ()), usize> and returns Fx<(), usize> let len_handler: RWHandler = |fx: Fx<'static, (fn(String) -> Fx<'static, (), usize>, ()), usize>| { fx.provide_left(|s: String| Fx::pure(s.len())) }; let effect: Fx<'static, (fn(String) -> Fx<'static, (), usize>, ()), usize> = Fx::func(|s: String| Fx::pure(s.len())); let handled: Fx<'static, (), usize> = len_handler.handle(effect); let result = handled.eval(); assert_eq!(result, "hello".len()); }
Requesting Handlers from the Environment
You can also request that a handler be present as a requirement. This way, the handler is provided once and can be applied anywhere in the program.
#![allow(unused)] fn main() { use fx::Fx; use fx::Handler; // Type alias for handler effect type RWHandler = Fx<Env, Output>; let len_handler: RWHandler = |fx: Fx<'static, (fn(String) -> Fx<'static, (), usize>, ()), usize>| { fx.provide_left(|s: String| Fx::pure(s.len())) }; let effect: Fx<'static, (fn(String) -> Fx<'static, (), usize>, ()), usize> = Fx::func(|s: String| Fx::pure(s.len())); let provided = effect.provide_left(len_handler); let result = provided.eval(); assert_eq!(result, "hello".len()); }
Handlers in fx-rs are just values and can be passed, composed, or swapped as needed.
A Handler in fx-rs is a transformation: it takes an input (often an effectful request or ability) and produces a new effect. Conceptually, a handler is a function that interprets or transforms effects, often by providing implementations for abilities or by composing/rewriting effects. See the comment in handler.rs
for details.
An Ability is a trait or type that represents a capability or effectful operation. In fx-rs, an ability is conceptually a function of the form I => Fx<S, O>
, meaning it takes an input I
and returns an effectful computation producing an output O
and possibly requiring further abilities S
. See the comment in ability.rs
for the canonical definition.