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}