fp_library/classes/once.rs
1use crate::{hkt::Kind0L1T, make_type_apply};
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: Kind0L1T {
8 type Output<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>() -> ApplyOnce<Self, 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: &ApplyOnce<Self, 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>(a: &mut ApplyOnce<Self, A>) -> Option<&mut A>;
86
87 /// Sets the value of the container.
88 ///
89 /// Returns `Ok(())` if the value was set, or `Err(value)` if the container was already initialized.
90 ///
91 /// # Type Signature
92 ///
93 /// `forall a. Once f => (f a, a) -> Result<(), a>`
94 ///
95 /// # Parameters
96 ///
97 /// * `a`: The container.
98 /// * `value`: The value to set.
99 ///
100 /// # Returns
101 ///
102 /// `Ok(())` on success, or `Err(value)` if already initialized.
103 ///
104 /// # Examples
105 ///
106 /// ```
107 /// use fp_library::classes::once::Once;
108 /// use fp_library::brands::OnceCellBrand;
109 ///
110 /// let cell = <OnceCellBrand as Once>::new::<i32>();
111 /// assert!(<OnceCellBrand as Once>::set(&cell, 42).is_ok());
112 /// assert!(<OnceCellBrand as Once>::set(&cell, 10).is_err());
113 /// ```
114 fn set<A>(
115 a: &ApplyOnce<Self, A>,
116 value: A,
117 ) -> Result<(), A>;
118
119 /// Gets the value, initializing it with the closure `f` if it is not already initialized.
120 ///
121 /// # Type Signature
122 ///
123 /// `forall a. Once f => (f a, () -> a) -> a`
124 ///
125 /// # Parameters
126 ///
127 /// * `a`: The container.
128 /// * `f`: The initialization function.
129 ///
130 /// # Returns
131 ///
132 /// A reference to the value.
133 ///
134 /// # Examples
135 ///
136 /// ```
137 /// use fp_library::classes::once::Once;
138 /// use fp_library::brands::OnceCellBrand;
139 ///
140 /// let cell = <OnceCellBrand as Once>::new::<i32>();
141 /// assert_eq!(*<OnceCellBrand as Once>::get_or_init(&cell, || 42), 42);
142 /// assert_eq!(*<OnceCellBrand as Once>::get_or_init(&cell, || 10), 42);
143 /// ```
144 fn get_or_init<A, B: FnOnce() -> A>(
145 a: &ApplyOnce<Self, A>,
146 f: B,
147 ) -> &A;
148
149 /// Consumes the container and returns the value if it has been initialized.
150 ///
151 /// # Type Signature
152 ///
153 /// `forall a. Once f => f a -> Option a`
154 ///
155 /// # Parameters
156 ///
157 /// * `a`: The container.
158 ///
159 /// # Returns
160 ///
161 /// The value, or `None` if uninitialized.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// use fp_library::classes::once::Once;
167 /// use fp_library::brands::OnceCellBrand;
168 ///
169 /// let cell = <OnceCellBrand as Once>::new::<i32>();
170 /// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
171 /// assert_eq!(<OnceCellBrand as Once>::into_inner(cell), Some(42));
172 /// ```
173 fn into_inner<A>(a: ApplyOnce<Self, A>) -> Option<A>;
174
175 /// Takes the value out of the container, leaving it uninitialized.
176 ///
177 /// # Type Signature
178 ///
179 /// `forall a. Once f => f a -> Option a`
180 ///
181 /// # Parameters
182 ///
183 /// * `a`: The container.
184 ///
185 /// # Returns
186 ///
187 /// The value, or `None` if uninitialized.
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// use fp_library::classes::once::Once;
193 /// use fp_library::brands::OnceCellBrand;
194 ///
195 /// let mut cell = <OnceCellBrand as Once>::new::<i32>();
196 /// <OnceCellBrand as Once>::set(&cell, 42).unwrap();
197 /// assert_eq!(<OnceCellBrand as Once>::take(&mut cell), Some(42));
198 /// assert_eq!(<OnceCellBrand as Once>::take(&mut cell), None);
199 /// ```
200 fn take<A>(a: &mut ApplyOnce<Self, A>) -> Option<A>;
201}
202
203make_type_apply!(ApplyOnce, Once, (), (A), "* -> *");
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>() -> ApplyOnce<F, 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: &ApplyOnce<F, 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>(a: &mut ApplyOnce<F, A>) -> Option<&mut A>
298where
299 F: Once,
300{
301 F::get_mut(a)
302}
303
304/// Sets the value of the container.
305///
306/// Returns `Ok(())` if the value was set, or `Err(value)` if the container was already initialized.
307///
308/// Free function version that dispatches to [the type class' associated function][`Once::set`].
309///
310/// # Type Signature
311///
312/// `forall a. Once f => (f a, a) -> Result<(), a>`
313///
314/// # Parameters
315///
316/// * `a`: The container.
317/// * `value`: The value to set.
318///
319/// # Returns
320///
321/// `Ok(())` on success, or `Err(value)` if already initialized.
322///
323/// # Examples
324///
325/// ```
326/// use fp_library::classes::once::{new, set};
327/// use fp_library::brands::OnceCellBrand;
328///
329/// let cell = new::<OnceCellBrand, i32>();
330/// assert!(set::<OnceCellBrand, _>(&cell, 42).is_ok());
331/// assert!(set::<OnceCellBrand, _>(&cell, 10).is_err());
332/// ```
333pub fn set<F, A>(
334 a: &ApplyOnce<F, A>,
335 value: A,
336) -> Result<(), A>
337where
338 F: Once,
339{
340 F::set(a, value)
341}
342
343/// Gets the value, initializing it with the closure `f` if it is not already initialized.
344///
345/// Free function version that dispatches to [the type class' associated function][`Once::get_or_init`].
346///
347/// # Type Signature
348///
349/// `forall a. Once f => (f a, () -> a) -> a`
350///
351/// # Parameters
352///
353/// * `a`: The container.
354/// * `f`: The initialization function.
355///
356/// # Returns
357///
358/// A reference to the value.
359///
360/// # Examples
361///
362/// ```
363/// use fp_library::classes::once::{new, get_or_init};
364/// use fp_library::brands::OnceCellBrand;
365///
366/// let cell = new::<OnceCellBrand, i32>();
367/// assert_eq!(*get_or_init::<OnceCellBrand, _, _>(&cell, || 42), 42);
368/// assert_eq!(*get_or_init::<OnceCellBrand, _, _>(&cell, || 10), 42);
369/// ```
370pub fn get_or_init<F, A, B>(
371 a: &ApplyOnce<F, A>,
372 f: B,
373) -> &A
374where
375 F: Once,
376 B: FnOnce() -> A,
377{
378 F::get_or_init(a, f)
379}
380
381/// Consumes the container and returns the value if it has been initialized.
382///
383/// Free function version that dispatches to [the type class' associated function][`Once::into_inner`].
384///
385/// # Type Signature
386///
387/// `forall a. Once f => f a -> Option a`
388///
389/// # Parameters
390///
391/// * `a`: The container.
392///
393/// # Returns
394///
395/// The value, or `None` if uninitialized.
396///
397/// # Examples
398///
399/// ```
400/// use fp_library::classes::once::{new, set, into_inner};
401/// use fp_library::brands::OnceCellBrand;
402///
403/// let cell = new::<OnceCellBrand, i32>();
404/// set::<OnceCellBrand, _>(&cell, 42).unwrap();
405/// assert_eq!(into_inner::<OnceCellBrand, _>(cell), Some(42));
406/// ```
407pub fn into_inner<F, A>(a: ApplyOnce<F, A>) -> Option<A>
408where
409 F: Once,
410{
411 F::into_inner(a)
412}
413
414/// Takes the value out of the container, leaving it uninitialized.
415///
416/// Free function version that dispatches to [the type class' associated function][`Once::take`].
417///
418/// # Type Signature
419///
420/// `forall a. Once f => f a -> Option a`
421///
422/// # Parameters
423///
424/// * `a`: The container.
425///
426/// # Returns
427///
428/// The value, or `None` if uninitialized.
429///
430/// # Examples
431///
432/// ```
433/// use fp_library::classes::once::{new, set, take};
434/// use fp_library::brands::OnceCellBrand;
435///
436/// let mut cell = new::<OnceCellBrand, i32>();
437/// set::<OnceCellBrand, _>(&cell, 42).unwrap();
438/// assert_eq!(take::<OnceCellBrand, _>(&mut cell), Some(42));
439/// assert_eq!(take::<OnceCellBrand, _>(&mut cell), None);
440/// ```
441pub fn take<F, A>(a: &mut ApplyOnce<F, A>) -> Option<A>
442where
443 F: Once,
444{
445 F::take(a)
446}