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}