Crate effing_mad

source ·
Expand description

This library brings typed effects to Rust in a flexible and composable way. By building on Generators, 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 can println!() 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

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.