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}