fp_library/classes/
defer.rs

1use super::clonable_fn::{ApplyClonableFn, ClonableFn};
2
3/// A type class for types that can be constructed lazily.
4pub trait Defer<'a> {
5	/// Creates a value from a computation that produces the value.
6	///
7	/// # Type Signature
8	///
9	/// `forall a. Defer d => (() -> d a) -> d a`
10	///
11	/// # Parameters
12	///
13	/// * `f`: A thunk (wrapped in a clonable function) that produces the value.
14	///
15	/// # Returns
16	///
17	/// The deferred value.
18	///
19	/// # Examples
20	///
21	/// ```
22	/// use fp_library::classes::defer::Defer;
23	/// use fp_library::types::lazy::Lazy;
24	/// use fp_library::brands::RcFnBrand;
25	/// use fp_library::brands::OnceCellBrand;
26	/// use fp_library::classes::clonable_fn::ClonableFn;
27	///
28	/// let lazy = Lazy::<OnceCellBrand, RcFnBrand, _>::defer::<RcFnBrand>(
29	///     <RcFnBrand as ClonableFn>::new(|_| Lazy::new(<RcFnBrand as ClonableFn>::new(|_| 42)))
30	/// );
31	/// assert_eq!(Lazy::force(lazy), 42);
32	/// ```
33	fn defer<ClonableFnBrand: 'a + ClonableFn>(
34		f: ApplyClonableFn<'a, ClonableFnBrand, (), Self>
35	) -> Self
36	where
37		Self: Sized;
38}
39
40/// Creates a value from a computation that produces the value.
41///
42/// Free function version that dispatches to [the type class' associated function][`Defer::defer`].
43///
44/// # Type Signature
45///
46/// `forall a. Defer d => (() -> d a) -> d a`
47///
48/// # Parameters
49///
50/// * `f`: A thunk (wrapped in a clonable function) that produces the value.
51///
52/// # Returns
53///
54/// The deferred value.
55///
56/// # Examples
57///
58/// ```
59/// use fp_library::classes::defer::defer;
60/// use fp_library::types::lazy::Lazy;
61/// use fp_library::brands::RcFnBrand;
62/// use fp_library::brands::OnceCellBrand;
63/// use fp_library::classes::clonable_fn::ClonableFn;
64///
65/// let lazy = defer::<Lazy<OnceCellBrand, RcFnBrand, _>, RcFnBrand>(
66///     <RcFnBrand as ClonableFn>::new(|_| Lazy::new(<RcFnBrand as ClonableFn>::new(|_| 42)))
67/// );
68/// assert_eq!(Lazy::force(lazy), 42);
69/// ```
70pub fn defer<'a, D, ClonableFnBrand>(f: ApplyClonableFn<'a, ClonableFnBrand, (), D>) -> D
71where
72	D: Defer<'a>,
73	ClonableFnBrand: 'a + ClonableFn,
74{
75	D::defer::<ClonableFnBrand>(f)
76}