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