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