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}