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