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