fp_library/classes/once.rs
1//! A type class for containers that hold a value that is initialized at most once.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{brands::*, functions::*};
7//!
8//! let cell = once_new::<OnceCellBrand, i32>();
9//! assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
10//! ```
11
12use crate::kinds::*;
13
14/// A type class for containers that hold a value that is initialized at most once.
15///
16/// It provides methods for initialization, access, and consumption.
17pub trait Once: Kind_ad6c20556a82a1f0 {
18 type Of<A>;
19
20 /// Creates a new, uninitialized `Once` container.
21 ///
22 /// This method creates a new instance of the container that is initially empty.
23 ///
24 /// ### Type Signature
25 ///
26 /// `forall a. Once f => () -> f a`
27 ///
28 /// ### Type Parameters
29 ///
30 /// * `A`: The type of the value to be stored in the container.
31 ///
32 /// ### Returns
33 ///
34 /// A new, empty container.
35 ///
36 /// ### Examples
37 ///
38 /// ```
39 /// use fp_library::{brands::*, functions::*};
40 ///
41 /// let cell = once_new::<OnceCellBrand, i32>();
42 /// assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
43 /// ```
44 fn new<A>() -> <Self as Once>::Of<A>;
45
46 /// Gets a reference to the value if it has been initialized.
47 ///
48 /// This method returns a reference to the value stored in the container if it has been initialized, otherwise it returns `None`.
49 ///
50 /// ### Type Signature
51 ///
52 /// `forall a. Once f => f a -> Option a`
53 ///
54 /// ### Type Parameters
55 ///
56 /// * `A`: The type of the value stored in the container.
57 ///
58 /// ### Parameters
59 ///
60 /// * `a`: The container.
61 ///
62 /// ### Returns
63 ///
64 /// A reference to the value, or `None` if uninitialized.
65 ///
66 /// ### Examples
67 ///
68 /// ```
69 /// use fp_library::{brands::*, functions::*};
70 ///
71 /// let cell = once_new::<OnceCellBrand, i32>();
72 /// assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
73 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
74 /// assert_eq!(once_get::<OnceCellBrand, _>(&cell), Some(&42));
75 /// ```
76 fn get<A>(a: &<Self as Once>::Of<A>) -> Option<&A>;
77
78 /// Gets a mutable reference to the value if it has been initialized.
79 ///
80 /// This method returns a mutable reference to the value stored in the container if it has been initialized, otherwise it returns `None`.
81 ///
82 /// ### Type Signature
83 ///
84 /// `forall a. Once f => f a -> Option a`
85 ///
86 /// ### Type Parameters
87 ///
88 /// * `A`: The type of the value stored in the container.
89 ///
90 /// ### Parameters
91 ///
92 /// * `a`: The container.
93 ///
94 /// ### Returns
95 ///
96 /// A mutable reference to the value, or `None` if uninitialized.
97 ///
98 /// ### Examples
99 ///
100 /// ```
101 /// use fp_library::{brands::*, functions::*};
102 ///
103 /// let mut cell = once_new::<OnceCellBrand, i32>();
104 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
105 /// if let Some(val) = once_get_mut::<OnceCellBrand, _>(&mut cell) {
106 /// *val += 1;
107 /// }
108 /// assert_eq!(once_get_mut::<OnceCellBrand, _>(&mut cell), Some(&mut 43));
109 /// ```
110 fn get_mut<A>(a: &mut <Self as Once>::Of<A>) -> Option<&mut A>;
111
112 /// Sets the value of the container.
113 ///
114 /// This method attempts to set the value of the container. If the container is already initialized, it returns the value in the `Err` variant.
115 ///
116 /// ### Type Signature
117 ///
118 /// `forall a. Once f => (f a, a) -> Result<(), a>`
119 ///
120 /// ### Type Parameters
121 ///
122 /// * `A`: The type of the value to set.
123 ///
124 /// ### Parameters
125 ///
126 /// * `a`: The container.
127 /// * `value`: The value to set.
128 ///
129 /// ### Returns
130 ///
131 /// `Ok(())` on success, or `Err(value)` if already initialized.
132 ///
133 /// ### Examples
134 ///
135 /// ```
136 /// use fp_library::{brands::*, functions::*};
137 ///
138 /// let cell = once_new::<OnceCellBrand, i32>();
139 /// assert!(once_set::<OnceCellBrand, _>(&cell, 42).is_ok());
140 /// assert!(once_set::<OnceCellBrand, _>(&cell, 10).is_err());
141 /// ```
142 fn set<A>(
143 a: &<Self as Once>::Of<A>,
144 value: A,
145 ) -> Result<(), A>;
146
147 /// Gets the value, initializing it with the closure `f` if it is not already initialized.
148 ///
149 /// This method returns a reference to the value stored in the container. If the container is not initialized, it initializes it using the provided closure `f` and then returns a reference to the value.
150 ///
151 /// ### Type Signature
152 ///
153 /// `forall a. Once f => (f a, () -> a) -> a`
154 ///
155 /// ### Type Parameters
156 ///
157 /// * `A`: The type of the value stored in the container.
158 /// * `B`: The type of the initialization function.
159 ///
160 /// ### Parameters
161 ///
162 /// * `a`: The container.
163 /// * `f`: The initialization function.
164 ///
165 /// ### Returns
166 ///
167 /// A reference to the value.
168 ///
169 /// ### Examples
170 ///
171 /// ```
172 /// use fp_library::{brands::*, functions::*};
173 ///
174 /// let cell = once_new::<OnceCellBrand, i32>();
175 /// assert_eq!(*once_get_or_init::<OnceCellBrand, _, _>(&cell, || 42), 42);
176 /// assert_eq!(*once_get_or_init::<OnceCellBrand, _, _>(&cell, || 10), 42);
177 /// ```
178 fn get_or_init<A, B: FnOnce() -> A>(
179 a: &<Self as Once>::Of<A>,
180 f: B,
181 ) -> &A;
182
183 /// Consumes the container and returns the value if it has been initialized.
184 ///
185 /// This method consumes the container and returns the value stored in it if it has been initialized, otherwise it returns `None`.
186 ///
187 /// ### Type Signature
188 ///
189 /// `forall a. Once f => f a -> Option a`
190 ///
191 /// ### Type Parameters
192 ///
193 /// * `A`: The type of the value stored in the container.
194 ///
195 /// ### Parameters
196 ///
197 /// * `a`: The container.
198 ///
199 /// ### Returns
200 ///
201 /// The value, or `None` if uninitialized.
202 ///
203 /// ### Examples
204 ///
205 /// ```
206 /// use fp_library::{brands::*, functions::*};
207 ///
208 /// let cell = once_new::<OnceCellBrand, i32>();
209 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
210 /// assert_eq!(once_into_inner::<OnceCellBrand, _>(cell), Some(42));
211 /// ```
212 fn into_inner<A>(a: <Self as Once>::Of<A>) -> Option<A>;
213
214 /// Takes the value out of the container, leaving it uninitialized.
215 ///
216 /// This method takes the value out of the container, leaving the container in an uninitialized state. It returns the value if it was initialized, otherwise it returns `None`.
217 ///
218 /// ### Type Signature
219 ///
220 /// `forall a. Once f => f a -> Option a`
221 ///
222 /// ### Type Parameters
223 ///
224 /// * `A`: The type of the value stored in the container.
225 ///
226 /// ### Parameters
227 ///
228 /// * `a`: The container.
229 ///
230 /// ### Returns
231 ///
232 /// The value, or `None` if uninitialized.
233 ///
234 /// ### Examples
235 ///
236 /// ```
237 /// use fp_library::{brands::*, functions::*};
238 ///
239 /// let mut cell = once_new::<OnceCellBrand, i32>();
240 /// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
241 /// assert_eq!(once_take::<OnceCellBrand, _>(&mut cell), Some(42));
242 /// assert_eq!(once_take::<OnceCellBrand, _>(&mut cell), None);
243 /// ```
244 fn take<A>(a: &mut <Self as Once>::Of<A>) -> Option<A>;
245}
246
247/// Creates a new, uninitialized `Once` container.
248///
249/// Free function version that dispatches to [the type class' associated function][`Once::new`].
250///
251/// ### Type Signature
252///
253/// `forall a. Once f => () -> f a`
254///
255/// ### Type Parameters
256///
257/// * `Brand`: The brand of the container.
258/// * `A`: The type of the value to be stored in the container.
259///
260/// ### Returns
261///
262/// A new, empty container.
263///
264/// ### Examples
265///
266/// ```
267/// use fp_library::{brands::*, functions::*};
268///
269/// let cell = once_new::<OnceCellBrand, i32>();
270/// assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
271/// ```
272pub fn new<Brand, A>() -> <Brand as Once>::Of<A>
273where
274 Brand: Once,
275{
276 Brand::new()
277}
278
279/// Gets a reference to the value if it has been initialized.
280///
281/// Free function version that dispatches to [the type class' associated function][`Once::get`].
282///
283/// ### Type Signature
284///
285/// `forall a. Once f => f a -> Option a`
286///
287/// ### Type Parameters
288///
289/// * `Brand`: The brand of the container.
290/// * `A`: The type of the value stored in the container.
291///
292/// ### Parameters
293///
294/// * `a`: The container.
295///
296/// ### Returns
297///
298/// A reference to the value, or `None` if uninitialized.
299///
300/// ### Examples
301///
302/// ```
303/// use fp_library::{brands::*, functions::*};
304///
305/// let cell = once_new::<OnceCellBrand, i32>();
306/// assert_eq!(once_get::<OnceCellBrand, _>(&cell), None);
307/// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
308/// assert_eq!(once_get::<OnceCellBrand, _>(&cell), Some(&42));
309/// ```
310pub fn get<Brand, A>(a: &<Brand as Once>::Of<A>) -> Option<&A>
311where
312 Brand: Once,
313{
314 Brand::get(a)
315}
316
317/// Gets a mutable reference to the value if it has been initialized.
318///
319/// Free function version that dispatches to [the type class' associated function][`Once::get_mut`].
320///
321/// ### Type Signature
322///
323/// `forall a. Once f => f a -> Option a`
324///
325/// ### Type Parameters
326///
327/// * `Brand`: The brand of the container.
328/// * `A`: The type of the value stored in the container.
329///
330/// ### Parameters
331///
332/// * `a`: The container.
333///
334/// ### Returns
335///
336/// A mutable reference to the value, or `None` if uninitialized.
337///
338/// ### Examples
339///
340/// ```
341/// use fp_library::{brands::*, functions::*};
342///
343/// let mut cell = once_new::<OnceCellBrand, i32>();
344/// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
345/// if let Some(val) = once_get_mut::<OnceCellBrand, _>(&mut cell) {
346/// *val += 1;
347/// }
348/// assert_eq!(once_get_mut::<OnceCellBrand, _>(&mut cell), Some(&mut 43));
349/// ```
350pub fn get_mut<Brand, A>(a: &mut <Brand as Once>::Of<A>) -> Option<&mut A>
351where
352 Brand: Once,
353{
354 Brand::get_mut(a)
355}
356
357/// Sets the value of the container.
358///
359/// This function attempts to set the value of the container. If the container is already initialized, it returns the value in the `Err` variant.
360///
361/// Free function version that dispatches to [the type class' associated function][`Once::set`].
362///
363/// ### Type Signature
364///
365/// `forall a. Once f => (f a, a) -> Result<(), a>`
366///
367/// ### Type Parameters
368///
369/// * `Brand`: The brand of the container.
370/// * `A`: The type of the value to set.
371///
372/// ### Parameters
373///
374/// * `a`: The container.
375/// * `value`: The value to set.
376///
377/// ### Returns
378///
379/// `Ok(())` on success, or `Err(value)` if already initialized.
380///
381/// ### Examples
382///
383/// ```
384/// use fp_library::{brands::*, functions::*};
385///
386/// let cell = once_new::<OnceCellBrand, i32>();
387/// assert!(once_set::<OnceCellBrand, _>(&cell, 42).is_ok());
388/// assert!(once_set::<OnceCellBrand, _>(&cell, 10).is_err());
389/// ```
390pub fn set<Brand, A>(
391 a: &<Brand as Once>::Of<A>,
392 value: A,
393) -> Result<(), A>
394where
395 Brand: Once,
396{
397 Brand::set(a, value)
398}
399
400/// Gets the value, initializing it with the closure `f` if it is not already initialized.
401///
402/// Free function version that dispatches to [the type class' associated function][`Once::get_or_init`].
403///
404/// ### Type Signature
405///
406/// `forall a. Once f => (f a, () -> a) -> a`
407///
408/// ### Type Parameters
409///
410/// * `Brand`: The brand of the container.
411/// * `A`: The type of the value stored in the container.
412/// * `B`: The type of the initialization function.
413///
414/// ### Parameters
415///
416/// * `a`: The container.
417/// * `f`: The initialization function.
418///
419/// ### Returns
420///
421/// A reference to the value.
422///
423/// ### Examples
424///
425/// ```
426/// use fp_library::{brands::*, functions::*};
427///
428/// let cell = once_new::<OnceCellBrand, i32>();
429/// assert_eq!(*once_get_or_init::<OnceCellBrand, _, _>(&cell, || 42), 42);
430/// assert_eq!(*once_get_or_init::<OnceCellBrand, _, _>(&cell, || 10), 42);
431/// ```
432pub fn get_or_init<Brand, A, B>(
433 a: &<Brand as Once>::Of<A>,
434 f: B,
435) -> &A
436where
437 Brand: Once,
438 B: FnOnce() -> A,
439{
440 Brand::get_or_init(a, f)
441}
442
443/// Consumes the container and returns the value if it has been initialized.
444///
445/// Free function version that dispatches to [the type class' associated function][`Once::into_inner`].
446///
447/// ### Type Signature
448///
449/// `forall a. Once f => f a -> Option a`
450///
451/// ### Type Parameters
452///
453/// * `Brand`: The brand of the container.
454/// * `A`: The type of the value stored in the container.
455///
456/// ### Parameters
457///
458/// * `a`: The container.
459///
460/// ### Returns
461///
462/// The value, or `None` if uninitialized.
463///
464/// ### Examples
465///
466/// ```
467/// use fp_library::{brands::*, functions::*};
468///
469/// let cell = once_new::<OnceCellBrand, i32>();
470/// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
471/// assert_eq!(once_into_inner::<OnceCellBrand, _>(cell), Some(42));
472/// ```
473pub fn into_inner<Brand, A>(a: <Brand as Once>::Of<A>) -> Option<A>
474where
475 Brand: Once,
476{
477 Brand::into_inner(a)
478}
479
480/// Takes the value out of the container, leaving it uninitialized.
481///
482/// Free function version that dispatches to [the type class' associated function][`Once::take`].
483///
484/// ### Type Signature
485///
486/// `forall a. Once f => f a -> Option a`
487///
488/// ### Type Parameters
489///
490/// * `Brand`: The brand of the container.
491/// * `A`: The type of the value stored in the container.
492///
493/// ### Parameters
494///
495/// * `a`: The container.
496///
497/// ### Returns
498///
499/// The value, or `None` if uninitialized.
500///
501/// ### Examples
502///
503/// ```
504/// use fp_library::{brands::*, functions::*};
505///
506/// let mut cell = once_new::<OnceCellBrand, i32>();
507/// once_set::<OnceCellBrand, _>(&cell, 42).unwrap();
508/// assert_eq!(once_take::<OnceCellBrand, _>(&mut cell), Some(42));
509/// assert_eq!(once_take::<OnceCellBrand, _>(&mut cell), None);
510/// ```
511pub fn take<Brand, A>(a: &mut <Brand as Once>::Of<A>) -> Option<A>
512where
513 Brand: Once,
514{
515 Brand::take(a)
516}