Skip to main content

fp_library/classes/
deferrable.rs

1//! Types that can be constructed lazily from a computation.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{brands::*, functions::*, types::*};
7//!
8//! let eval: Thunk<i32> = defer(|| Thunk::new(|| 42));
9//! assert_eq!(eval.evaluate(), 42);
10//! ```
11
12use fp_macros::doc_params;
13use fp_macros::doc_type_params;
14use fp_macros::hm_signature;
15
16/// A type class for types that can be constructed lazily.
17pub trait Deferrable<'a> {
18	/// Creates a value from a computation that produces the value.
19	///
20	/// This function takes a thunk and creates a deferred value that will be computed using the thunk.
21	///
22	/// ### Type Signature
23	///
24	#[hm_signature(Deferrable)]
25	///
26	/// ### Type Parameters
27	///
28	#[doc_type_params("The type of the thunk.")]
29	///
30	/// ### Parameters
31	///
32	#[doc_params("A thunk that produces the value.")]
33	///
34	/// ### Returns
35	///
36	/// The deferred value.
37	///
38	/// ### Examples
39	///
40	/// ```
41	/// use fp_library::{brands::*, functions::*, types::*};
42	///
43	/// let eval: Thunk<i32> = defer(|| Thunk::new(|| 42));
44	/// assert_eq!(eval.evaluate(), 42);
45	/// ```
46	fn defer<F>(f: F) -> Self
47	where
48		F: FnOnce() -> Self + 'a,
49		Self: Sized;
50}
51
52/// Creates a value from a computation that produces the value.
53///
54/// Free function version that dispatches to [the type class' associated function][`Deferrable::defer`].
55///
56/// ### Type Signature
57///
58#[hm_signature(Deferrable)]
59///
60/// ### Type Parameters
61///
62#[doc_type_params(
63	"The lifetime of the computation",
64	"The type of the deferred value.",
65	"The type of the thunk."
66)]
67///
68/// ### Parameters
69///
70#[doc_params("A thunk that produces the value.")]
71///
72/// ### Returns
73///
74/// The deferred value.
75///
76/// ### Examples
77///
78/// ```
79/// use fp_library::{brands::*, functions::*, types::*};
80///
81/// let eval: Thunk<i32> = defer(|| Thunk::new(|| 42));
82/// assert_eq!(eval.evaluate(), 42);
83/// ```
84pub fn defer<'a, D, F>(f: F) -> D
85where
86	D: Deferrable<'a>,
87	F: FnOnce() -> D + 'a,
88{
89	D::defer(f)
90}