fp_library/classes/
compactable.rs

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