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::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_ad6c20556a82a1f0 {
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>() -> <Self as Once>::Of<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: &<Self as Once>::Of<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>(a: &mut <Self as Once>::Of<A>) -> Option<&mut A>;
108
109	/// Sets the value of the container.
110	///
111	/// This method attempts to set the value of the container. If the container is already initialized, it returns the value in the `Err` variant.
112	///
113	/// ### Type Signature
114	///
115	/// `forall a. Once f => (f a, a) -> Result<(), a>`
116	///
117	/// ### Type Parameters
118	///
119	/// * `A`: The type of the value to set.
120	///
121	/// ### Parameters
122	///
123	/// * `a`: The container.
124	/// * `value`: The value to set.
125	///
126	/// ### Returns
127	///
128	/// `Ok(())` on success, or `Err(value)` if already initialized.
129	///
130	/// ### Examples
131	///
132	/// ```
133	/// use fp_library::classes::once::Once;
134	/// use fp_library::brands::OnceCellBrand;
135	///
136	/// let cell = <OnceCellBrand as Once>::new::<i32>();
137	/// assert!(<OnceCellBrand as Once>::set(&cell, 42).is_ok());
138	/// assert!(<OnceCellBrand as Once>::set(&cell, 10).is_err());
139	/// ```
140	fn set<A>(
141		a: &<Self as Once>::Of<A>,
142		value: A,
143	) -> Result<(), A>;
144
145	/// Gets the value, initializing it with the closure `f` if it is not already initialized.
146	///
147	/// 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.
148	///
149	/// ### Type Signature
150	///
151	/// `forall a. Once f => (f a, () -> a) -> a`
152	///
153	/// ### Type Parameters
154	///
155	/// * `A`: The type of the value stored in the container.
156	/// * `B`: The type of the initialization function.
157	///
158	/// ### Parameters
159	///
160	/// * `a`: The container.
161	/// * `f`: The initialization function.
162	///
163	/// ### Returns
164	///
165	/// A reference to the value.
166	///
167	/// ### Examples
168	///
169	/// ```
170	/// use fp_library::classes::once::Once;
171	/// use fp_library::brands::OnceCellBrand;
172	///
173	/// let cell = <OnceCellBrand as Once>::new::<i32>();
174	/// assert_eq!(*<OnceCellBrand as Once>::get_or_init(&cell, || 42), 42);
175	/// assert_eq!(*<OnceCellBrand as Once>::get_or_init(&cell, || 10), 42);
176	/// ```
177	fn get_or_init<A, B: FnOnce() -> A>(
178		a: &<Self as Once>::Of<A>,
179		f: B,
180	) -> &A;
181
182	/// Consumes the container and returns the value if it has been initialized.
183	///
184	/// This method consumes the container and returns the value stored in it if it has been initialized, otherwise it returns `None`.
185	///
186	/// ### Type Signature
187	///
188	/// `forall a. Once f => f a -> Option a`
189	///
190	/// ### Type Parameters
191	///
192	/// * `A`: The type of the value stored in the container.
193	///
194	/// ### Parameters
195	///
196	/// * `a`: The container.
197	///
198	/// ### Returns
199	///
200	/// The value, or `None` if uninitialized.
201	///
202	/// ### Examples
203	///
204	/// ```
205	/// use fp_library::classes::once::Once;
206	/// use fp_library::brands::OnceCellBrand;
207	///
208	/// let cell = <OnceCellBrand as Once>::new::<i32>();
209	/// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
210	/// assert_eq!(<OnceCellBrand as Once>::into_inner(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::classes::once::Once;
238	/// use fp_library::brands::OnceCellBrand;
239	///
240	/// let mut cell = <OnceCellBrand as Once>::new::<i32>();
241	/// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
242	/// assert_eq!(<OnceCellBrand as Once>::take(&mut cell), Some(42));
243	/// assert_eq!(<OnceCellBrand as Once>::take(&mut cell), None);
244	/// ```
245	fn take<A>(a: &mut <Self as Once>::Of<A>) -> Option<A>;
246}
247
248/// Creates a new, uninitialized `Once` container.
249///
250/// Free function version that dispatches to [the type class' associated function][`Once::new`].
251///
252/// ### Type Signature
253///
254/// `forall a. Once f => () -> f a`
255///
256/// ### Type Parameters
257///
258/// * `Brand`: The brand of the container.
259/// * `A`: The type of the value to be stored in the container.
260///
261/// ### Returns
262///
263/// A new, empty container.
264///
265/// ### Examples
266///
267/// ```
268/// use fp_library::classes::once::new;
269/// use fp_library::classes::once::get;
270/// use fp_library::brands::OnceCellBrand;
271///
272/// let cell = new::<OnceCellBrand, i32>();
273/// assert_eq!(get::<OnceCellBrand, _>(&cell), None);
274/// ```
275pub fn new<Brand, A>() -> <Brand as Once>::Of<A>
276where
277	Brand: Once,
278{
279	Brand::new()
280}
281
282/// Gets a reference to the value if it has been initialized.
283///
284/// Free function version that dispatches to [the type class' associated function][`Once::get`].
285///
286/// ### Type Signature
287///
288/// `forall a. Once f => f a -> Option a`
289///
290/// ### Type Parameters
291///
292/// * `Brand`: The brand of the container.
293/// * `A`: The type of the value stored in the container.
294///
295/// ### Parameters
296///
297/// * `a`: The container.
298///
299/// ### Returns
300///
301/// A reference to the value, or `None` if uninitialized.
302///
303/// ### Examples
304///
305/// ```
306/// use fp_library::classes::once::{new, get, set};
307/// use fp_library::brands::OnceCellBrand;
308///
309/// let cell = new::<OnceCellBrand, i32>();
310/// assert_eq!(get::<OnceCellBrand, _>(&cell), None);
311/// set::<OnceCellBrand, _>(&cell, 42).unwrap();
312/// assert_eq!(get::<OnceCellBrand, _>(&cell), Some(&42));
313/// ```
314pub fn get<Brand, A>(a: &<Brand as Once>::Of<A>) -> Option<&A>
315where
316	Brand: Once,
317{
318	Brand::get(a)
319}
320
321/// Gets a mutable reference to the value if it has been initialized.
322///
323/// Free function version that dispatches to [the type class' associated function][`Once::get_mut`].
324///
325/// ### Type Signature
326///
327/// `forall a. Once f => f a -> Option a`
328///
329/// ### Type Parameters
330///
331/// * `Brand`: The brand of the container.
332/// * `A`: The type of the value stored in the container.
333///
334/// ### Parameters
335///
336/// * `a`: The container.
337///
338/// ### Returns
339///
340/// A mutable reference to the value, or `None` if uninitialized.
341///
342/// ### Examples
343///
344/// ```
345/// use fp_library::classes::once::{new, get_mut, set};
346/// use fp_library::brands::OnceCellBrand;
347///
348/// let mut cell = new::<OnceCellBrand, i32>();
349/// set::<OnceCellBrand, _>(&cell, 42).unwrap();
350/// if let Some(val) = get_mut::<OnceCellBrand, _>(&mut cell) {
351///     *val += 1;
352/// }
353/// assert_eq!(get_mut::<OnceCellBrand, _>(&mut cell), Some(&mut 43));
354/// ```
355pub fn get_mut<Brand, A>(a: &mut <Brand as Once>::Of<A>) -> Option<&mut A>
356where
357	Brand: Once,
358{
359	Brand::get_mut(a)
360}
361
362/// Sets the value of the container.
363///
364/// This function attempts to set the value of the container. If the container is already initialized, it returns the value in the `Err` variant.
365///
366/// Free function version that dispatches to [the type class' associated function][`Once::set`].
367///
368/// ### Type Signature
369///
370/// `forall a. Once f => (f a, a) -> Result<(), a>`
371///
372/// ### Type Parameters
373///
374/// * `Brand`: The brand of the container.
375/// * `A`: The type of the value to set.
376///
377/// ### Parameters
378///
379/// * `a`: The container.
380/// * `value`: The value to set.
381///
382/// ### Returns
383///
384/// `Ok(())` on success, or `Err(value)` if already initialized.
385///
386/// ### Examples
387///
388/// ```
389/// use fp_library::classes::once::{new, set};
390/// use fp_library::brands::OnceCellBrand;
391///
392/// let cell = new::<OnceCellBrand, i32>();
393/// assert!(set::<OnceCellBrand, _>(&cell, 42).is_ok());
394/// assert!(set::<OnceCellBrand, _>(&cell, 10).is_err());
395/// ```
396pub fn set<Brand, A>(
397	a: &<Brand as Once>::Of<A>,
398	value: A,
399) -> Result<(), A>
400where
401	Brand: Once,
402{
403	Brand::set(a, value)
404}
405
406/// Gets the value, initializing it with the closure `f` if it is not already initialized.
407///
408/// Free function version that dispatches to [the type class' associated function][`Once::get_or_init`].
409///
410/// ### Type Signature
411///
412/// `forall a. Once f => (f a, () -> a) -> a`
413///
414/// ### Type Parameters
415///
416/// * `Brand`: The brand of the container.
417/// * `A`: The type of the value stored in the container.
418/// * `B`: The type of the initialization function.
419///
420/// ### Parameters
421///
422/// * `a`: The container.
423/// * `f`: The initialization function.
424///
425/// ### Returns
426///
427/// A reference to the value.
428///
429/// ### Examples
430///
431/// ```
432/// use fp_library::classes::once::{new, get_or_init};
433/// use fp_library::brands::OnceCellBrand;
434///
435/// let cell = new::<OnceCellBrand, i32>();
436/// assert_eq!(*get_or_init::<OnceCellBrand, _, _>(&cell, || 42), 42);
437/// assert_eq!(*get_or_init::<OnceCellBrand, _, _>(&cell, || 10), 42);
438/// ```
439pub fn get_or_init<Brand, A, B>(
440	a: &<Brand as Once>::Of<A>,
441	f: B,
442) -> &A
443where
444	Brand: Once,
445	B: FnOnce() -> A,
446{
447	Brand::get_or_init(a, f)
448}
449
450/// Consumes the container and returns the value if it has been initialized.
451///
452/// Free function version that dispatches to [the type class' associated function][`Once::into_inner`].
453///
454/// ### Type Signature
455///
456/// `forall a. Once f => f a -> Option a`
457///
458/// ### Type Parameters
459///
460/// * `Brand`: The brand of the container.
461/// * `A`: The type of the value stored in the container.
462///
463/// ### Parameters
464///
465/// * `a`: The container.
466///
467/// ### Returns
468///
469/// The value, or `None` if uninitialized.
470///
471/// ### Examples
472///
473/// ```
474/// use fp_library::classes::once::{new, set, into_inner};
475/// use fp_library::brands::OnceCellBrand;
476///
477/// let cell = new::<OnceCellBrand, i32>();
478/// set::<OnceCellBrand, _>(&cell, 42).unwrap();
479/// assert_eq!(into_inner::<OnceCellBrand, _>(cell), Some(42));
480/// ```
481pub fn into_inner<Brand, A>(a: <Brand as Once>::Of<A>) -> Option<A>
482where
483	Brand: Once,
484{
485	Brand::into_inner(a)
486}
487
488/// Takes the value out of the container, leaving it uninitialized.
489///
490/// Free function version that dispatches to [the type class' associated function][`Once::take`].
491///
492/// ### Type Signature
493///
494/// `forall a. Once f => f a -> Option a`
495///
496/// ### Type Parameters
497///
498/// * `Brand`: The brand of the container.
499/// * `A`: The type of the value stored in the container.
500///
501/// ### Parameters
502///
503/// * `a`: The container.
504///
505/// ### Returns
506///
507/// The value, or `None` if uninitialized.
508///
509/// ### Examples
510///
511/// ```
512/// use fp_library::classes::once::{new, set, take};
513/// use fp_library::brands::OnceCellBrand;
514///
515/// let mut cell = new::<OnceCellBrand, i32>();
516/// set::<OnceCellBrand, _>(&cell, 42).unwrap();
517/// assert_eq!(take::<OnceCellBrand, _>(&mut cell), Some(42));
518/// assert_eq!(take::<OnceCellBrand, _>(&mut cell), None);
519/// ```
520pub fn take<Brand, A>(a: &mut <Brand as Once>::Of<A>) -> Option<A>
521where
522	Brand: Once,
523{
524	Brand::take(a)
525}