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