fp_library/classes/send_defer.rs
1//! A trait for deferred lazy evaluation with thread-safe thunks.
2//!
3//! This module defines the [`SendDefer`] trait, which extends `Kind!(type Of<'a, A: 'a>: 'a;)`
4//! to support creating deferred values where the thunk is `Send + Sync`.
5//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{brands::*, functions::*, types::lazy::*};
10//!
11//! let lazy = send_defer::<LazyBrand<ArcLazyConfig>, _, _>(|| ArcLazy::new(ArcLazyConfig::new_thunk(|_| 42)));
12//! assert_eq!(Lazy::force(&lazy).unwrap(), &42);
13//! ```
14
15use crate::{Apply, kinds::*};
16
17/// A trait for deferred lazy evaluation with thread-safe thunks.
18///
19/// This is similar to `Defer`, but the thunk must be `Send + Sync`.
20pub trait SendDefer: Kind_cdc7cd43dac7585f {
21 /// Creates a deferred value from a thread-safe thunk.
22 ///
23 /// ### Type Signature
24 ///
25 /// `forall f a. (SendDefer f, Send a, Sync a) => (() -> a) -> f a`
26 ///
27 /// ### Type Parameters
28 ///
29 /// * `A`: The type of the value.
30 ///
31 /// ### Parameters
32 ///
33 /// * `thunk`: The function that produces the value.
34 ///
35 /// ### Returns
36 ///
37 /// A deferred value.
38 ///
39 /// ### Examples
40 ///
41 /// ```
42 /// use fp_library::{brands::*, functions::*, types::*};
43 ///
44 /// let lazy = send_defer::<LazyBrand<ArcLazyConfig>, _, _>(|| ArcLazy::new(ArcLazyConfig::new_thunk(|_| 42)));
45 /// assert_eq!(Lazy::force(&lazy).unwrap(), &42);
46 /// ```
47 fn send_defer<'a, A>(
48 thunk: impl 'a
49 + Fn() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
50 + Send
51 + Sync
52 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
53 where
54 A: Clone + Send + Sync + 'a;
55}
56
57/// Creates a deferred value from a thread-safe thunk.
58///
59/// Free function version that dispatches to [the type class' associated function][`SendDefer::send_defer`].
60///
61/// ### Type Signature
62///
63/// `forall f a. (SendDefer f, Send a, Sync a) => (() -> a) -> f a`
64///
65/// ### Type Parameters
66///
67/// * `Brand`: The brand of the deferred type.
68/// * `A`: The type of the value.
69/// * `F`: The type of the thunk.
70///
71/// ### Parameters
72///
73/// * `thunk`: The function that produces the value.
74///
75/// ### Returns
76///
77/// A deferred value.
78///
79/// ### Examples
80///
81/// ```
82/// use fp_library::{brands::*, functions::*, types::*};
83///
84/// let lazy = send_defer::<LazyBrand<ArcLazyConfig>, _, _>(|| ArcLazy::new(ArcLazyConfig::new_thunk(|_| 42)));
85/// assert_eq!(Lazy::force(&lazy).unwrap(), &42);
86/// ```
87pub fn send_defer<'a, Brand, A, F>(
88 thunk: F
89) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
90where
91 Brand: SendDefer,
92 A: Clone + Send + Sync + 'a,
93 F: 'a + Fn() -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) + Send + Sync,
94{
95 Brand::send_defer(thunk)
96}