Crate effing_mad
source ·Expand description
This library brings typed effects to Rust in a flexible and composable way. By building on
Generator
s, effectful computations can be expressed in a way that allows arbitrary and
swappable behaviour - any handler of the correct type can be applied to a computation, meaning
different semantics of effects can be selected at each call site of an effectful function.
Glossary
- effectful computation: an in-progress computation that uses effects. analogous to
Future
. - effectful function: a function that returns an effectful computation. analogous to
async fn
. - effect: you know, I’m actually not sure. I should ask one of my PL teachers. In this library though, an effect is a value that can be passed out of an effectful computation and into an effect handler, which produces another value to pass back in.
- injection: an
effing_mad
term referring to the value passed into a computation as a result of it running an effect. - “pure” function: a Rust function that does not use
effing_mad
effects. Rust is not a pure language (crudely, Rust code canprintln!()
whenever it wants) so these docs use quotes to indicate this meaning as opposed to the real meaning of pure, where functions do not use side effects.
Getting started
Define an Effect
. Now, you can define an #[effectful(…)]
function that uses it. Once you call this function, its effects can be handled one by one with
handle
. Handlers are “pure” Rust functions, but it’s easiest to construct them using
handler!
. Once all the effects have been handled away, a computation
can be driven with run
.
Interaction with async
There are two ways to bring together the async world and the effectful world. The first, and
simplest, is handle_async
. This allows you to handle the last effect in a computation using
a handler that is an async fn
.
The second, more freaky way is with the contents of effects::future
. These allow you to
convert between futures and effectful computations freely - namely the effectfulise
function
and the futurise
function will take your futures and your computations and abstract away all
the other nonsense in that module to get you the respective constructs.
Re-exports
pub use frunk;
Modules
- Standard effects and functions to make them useful.
- Effectful versions of standard higher-order functions.
- Implementation details of injections - values that come from running effects.
- Implementation details of the macros exported by
effing_mad
.
Macros
- Define a new group of effects.
- Define a handler for an effect or group of effects.
Enums
- An uninhabited type that can never be constructed.
Traits
- An effect that must be handled by the caller of an effectful computation, or propagated up the call stack.
- Types which represent multiple effects.
Functions
- Apply a “pure” handler to an effectful computation, handling one effect.
- Handle the last effect in a computation using an async handler.
- Apply a “pure” handler to an effectful computation, handling any number of effects.
- Handle all of the remaining effects in a computation using an async handler.
- Create a new effectful computation by applying a “pure” function to the return value of an existing computation.
- Run an effectful computation that has no effects.
- Handle one effect in the computation
g
by running other effects. - Handle one effect of
g
by running other effects that it already uses. - Handle one effect of
g
by running a new effect.
Attribute Macros
- Define an effectful function using
fn
-like syntax.