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