Skip to main content

fp_library/classes/
compactable.rs

1//! A type class for data structures that can be compacted (filtering out [`None`] values) and separated (splitting [`Result`] values).
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{brands::*, functions::*};
7//!
8//! let x = Some(Some(5));
9//! let y = compact::<OptionBrand, _>(x);
10//! assert_eq!(y, Some(5));
11//! ```
12
13use crate::{Apply, brands::OptionBrand, kinds::*, types::Pair};
14
15/// A type class for data structures that can be compacted and separated.
16///
17/// `Compactable` allows for:
18/// *   `compact`: Filtering out [`None`] values and unwrapping [`Some`] values from a structure of [`Option`]s.
19/// *   `separate`: Splitting a structure of [`Result`]s into a pair of structures, one containing the [`Err`] values and the other containing the [`Ok`] values.
20pub trait Compactable: Kind_cdc7cd43dac7585f {
21	/// Compacts a data structure of [`Option`]s, discarding [`None`] values and keeping [`Some`] values.
22	///
23	/// ### Type Signature
24	///
25	/// `forall a f. Compactable f => f (Option a) -> f a`
26	///
27	/// ### Type Parameters
28	///
29	/// * `A`: The type of the elements in the [`Option`].
30	///
31	/// ### Parameters
32	///
33	/// * `fa`: The data structure containing [`Option`] values.
34	///
35	/// ### Returns
36	///
37	/// A new data structure containing only the values from the [`Some`] variants.
38	///
39	/// ### Examples
40	///
41	/// ```
42	/// use fp_library::{brands::*, functions::*};
43	///
44	/// let x = Some(Some(5));
45	/// let y = compact::<OptionBrand, _>(x);
46	/// assert_eq!(y, Some(5));
47	///
48	/// let z = Some(None::<i32>);
49	/// let w = compact::<OptionBrand, _>(z);
50	/// assert_eq!(w, None);
51	/// ```
52	fn compact<'a, A: 'a>(
53		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
54			'a,
55			Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
56		>)
57	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>);
58
59	/// Separates a data structure of [`Result`]s into two data structures: one containing the [`Ok`] values and one containing the [`Err`] values.
60	///
61	/// ### Type Signature
62	///
63	/// `forall o e f. Compactable f => f (Result o e) -> (f o, f e)`
64	///
65	/// ### Type Parameters
66	///
67	/// * `O`: The type of the success values.
68	/// * `E`: The type of the error values.
69	///
70	/// ### Parameters
71	///
72	/// * `fa`: The data structure containing [`Result`] values.
73	///
74	/// ### Returns
75	///
76	/// A pair of data structures: the first containing the [`Ok`] values, and the second containing the [`Err`] values.
77	///
78	/// ### Examples
79	///
80	/// ```
81	/// use fp_library::{brands::*, functions::*, types::*};
82	///
83	/// let x: Option<Result<i32, &str>> = Some(Ok(5));
84	/// let Pair(oks, errs) = separate::<OptionBrand, _, _>(x);
85	/// assert_eq!(oks, Some(5));
86	/// assert_eq!(errs, None);
87	///
88	/// let y: Option<Result<i32, &str>> = Some(Err("error"));
89	/// let Pair(oks2, errs2) = separate::<OptionBrand, _, _>(y);
90	/// assert_eq!(oks2, None);
91	/// assert_eq!(errs2, Some("error"));
92	/// ```
93	fn separate<'a, O: 'a, E: 'a>(
94		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
95	) -> Pair<
96		Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
97		Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
98	>;
99}
100
101/// Compacts a data structure of [`Option`]s, discarding [`None`] values and keeping [`Some`] values.
102///
103/// Free function version that dispatches to [the type class' associated function][`Compactable::compact`].
104///
105/// ### Type Signature
106///
107/// `forall a f. Compactable f => f (Option a) -> f a`
108///
109/// ### Type Parameters
110///
111/// * `Brand`: The brand of the compactable structure.
112/// * `A`: The type of the elements in the [`Option`].
113///
114/// ### Parameters
115///
116/// * `fa`: The data structure containing [`Option`] values.
117///
118/// ### Returns
119///
120/// A new data structure containing only the values from the [`Some`] variants.
121///
122/// ### Examples
123///
124/// ```
125/// use fp_library::{brands::*, functions::*};
126///
127/// let x = Some(Some(5));
128/// let y = compact::<OptionBrand, _>(x);
129/// assert_eq!(y, Some(5));
130/// ```
131pub fn compact<'a, Brand: Compactable, A: 'a>(
132	fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
133		'a,
134		Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
135	>)
136) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
137	Brand::compact(fa)
138}
139
140/// Separates a data structure of [`Result`]s into two data structures: one containing the [`Ok`] values and one containing the [`Err`] values.
141///
142/// Free function version that dispatches to [the type class' associated function][`Compactable::separate`].
143///
144/// ### Type Signature
145///
146/// `forall o e f. Compactable f => f (Result o e) -> (f o, f e)`
147///
148/// ### Type Parameters
149///
150/// * `Brand`: The brand of the compactable structure.
151/// * `O`: The type of the success values.
152/// * `E`: The type of the error values.
153///
154/// ### Parameters
155///
156/// * `fa`: The data structure containing [`Result`] values.
157///
158/// ### Returns
159///
160/// A pair of data structures: the first containing the [`Ok`] values, and the second containing the [`Err`] values.
161///
162/// ### Examples
163///
164/// ```
165/// use fp_library::{brands::*, functions::*, types::*};
166///
167/// let x: Option<Result<i32, &str>> = Some(Ok(5));
168/// let Pair(oks, errs) = separate::<OptionBrand, _, _>(x);
169/// assert_eq!(oks, Some(5));
170/// assert_eq!(errs, None);
171/// ```
172pub fn separate<'a, Brand: Compactable, O: 'a, E: 'a>(
173	fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
174) -> Pair<
175	Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
176	Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
177> {
178	Brand::separate::<O, E>(fa)
179}