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}