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}