fp_library/classes/ref_applicative.rs
1//! By-ref applicative functors, combining [`RefPointed`](crate::classes::RefPointed) and [`RefSemiapplicative`](crate::classes::RefSemiapplicative).
2//!
3//! This is the by-ref counterpart of [`Applicative`](crate::classes::Applicative).
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::{
9//! brands::*,
10//! classes::*,
11//! functions::*,
12//! types::*,
13//! };
14//!
15//! // ref_pure clones a value into a Lazy context
16//! let x = ref_pure::<LazyBrand<RcLazyConfig>, _>(&42);
17//! assert_eq!(*x.evaluate(), 42);
18//!
19//! // ref_apply applies a wrapped by-ref function
20//! let f = RcLazy::pure(std::rc::Rc::new(|x: &i32| *x + 1) as std::rc::Rc<dyn Fn(&i32) -> i32>);
21//! let result = ref_apply::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _>(&f, &x);
22//! assert_eq!(*result.evaluate(), 43);
23//! ```
24
25#[fp_macros::document_module]
26mod inner {
27 use crate::classes::*;
28
29 /// A type class for by-ref applicative functors.
30 ///
31 /// Combines [`RefPointed`] (injecting values from references) with
32 /// [`RefSemiapplicative`] (applying wrapped by-ref functions).
33 ///
34 /// This is the by-ref counterpart of [`Applicative`]. Automatically
35 /// implemented for any type implementing both supertraits.
36 ///
37 /// A lawful `RefApplicative` must satisfy the applicative laws
38 /// (identity, composition, homomorphism, interchange) expressed
39 /// in terms of `ref_pure` and `ref_apply`. These mirror the
40 /// standard [`Applicative`] laws but with by-ref function wrappers:
41 ///
42 /// 1. **Identity**: `ref_apply(ref_pure(&id), v) = v` (evaluated values equal).
43 /// 2. **Homomorphism**: `ref_apply(ref_pure(&f), ref_pure(&x)) = ref_pure(&f(&x))`.
44 /// 3. **Interchange**: `ref_apply(u, ref_pure(&y)) = ref_apply(ref_pure(&(|f| f(&y))), u)`.
45 pub trait RefApplicative:
46 RefPointed + RefSemiapplicative + RefApplyFirst + RefApplySecond {
47 }
48
49 /// Blanket implementation of [`RefApplicative`].
50 #[document_type_parameters("The brand type.")]
51 impl<Brand> RefApplicative for Brand where
52 Brand: RefPointed + RefSemiapplicative + RefApplyFirst + RefApplySecond
53 {
54 }
55}
56
57pub use inner::*;