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}