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