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}