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}