fp_library/classes/
defer.rs

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