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}