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}