pub enum FreeAp<F, A>where
F: HKT + 'static,
A: 'static,{
Pure(A),
Ap(Box<dyn FreeApNode<F, A>>),
}Expand description
Free Applicative Functor — build applicative computations as data.
FreeAp<F, A> stores a computation tree where effects from F
can be statically analyzed before interpretation. Unlike Free<F, A>
(the free monad), effects in FreeAp do not depend on the results
of previous effects.
Pure(a) — a finished computation
Ap(node) — an effect step (existentially quantified)§Interpretation
The primary eliminator is retract, which collapses the tree into
F’s own applicative. To interpret into a different applicative M
via a natural transformation NT: F ~> M, apply NT at each
lift_f call site:
// Instead of fold_map:
let free_m: FreeAp<M, A> = build_tree_with(|effect| lift_f(NT::transform(effect)));
let result: M::Of<A> = free_m.retract();This decomposition (fold_map nt ≡ retract . hoist nt) is necessary
because Rust’s type system cannot dispatch a generic natural
transformation through trait objects (the intermediate type B is
erased, preventing compile-time monomorphization of NT::transform<B>).
§When to use FreeAp vs Free
- Use
FreeAp<F, A>when effects are independent and you want static analysis of the effect structure. - Use
Free<F, A>when later effects depend on earlier results (monadic sequencing).
Variants§
Implementations§
Source§impl<F, A> FreeAp<F, A>where
F: HKT + 'static,
A: 'static,
impl<F, A> FreeAp<F, A>where
F: HKT + 'static,
A: 'static,
Sourcepub fn lift_f(fa: <F as HKT>::Of<A>) -> FreeAp<F, A>
pub fn lift_f(fa: <F as HKT>::Of<A>) -> FreeAp<F, A>
Lift a single effect F<A> into the free applicative.
A: Clone is required because Apply::ap needs it.
Sourcepub fn fmap<B>(self, f: impl Fn(A) -> B + 'static) -> FreeAp<F, B>where
B: 'static,
pub fn fmap<B>(self, f: impl Fn(A) -> B + 'static) -> FreeAp<F, B>where
B: 'static,
Map a function over the result. No bounds on F required.
Sourcepub fn ap<B>(
ff: FreeAp<F, Box<dyn Fn(A) -> B>>,
fa: FreeAp<F, A>,
) -> FreeAp<F, B>where
B: 'static,
A: Clone,
pub fn ap<B>(
ff: FreeAp<F, Box<dyn Fn(A) -> B>>,
fa: FreeAp<F, A>,
) -> FreeAp<F, B>where
B: 'static,
A: Clone,
Applicative ap: apply a wrapped function to this value.
ff contains functions A → B, self contains A values.
Sourcepub fn retract(self) -> <F as HKT>::Of<A>where
F: Applicative,
pub fn retract(self) -> <F as HKT>::Of<A>where
F: Applicative,
Interpret by collapsing back into F itself.
Requires F: Applicative.
Sourcepub fn count_effects(&self) -> usize
pub fn count_effects(&self) -> usize
Count the number of lift_f effects in this computation tree.
This demonstrates the key advantage of free applicatives over free monads: the tree structure can be statically analyzed without interpretation.