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}