fp_library/classes/ref_compactable.rs
1//! By-reference compacting and separating of structures.
2//!
3//! Similar to [`Compactable`](crate::classes::Compactable), but operates on borrowed containers. Elements are cloned
4//! out of the borrowed structure, so the element types must implement [`Clone`].
5//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{
10//! brands::*,
11//! functions::explicit::*,
12//! };
13//!
14//! let v = vec![Some(1), None, Some(3)];
15//! let result = compact::<VecBrand, _, _, _>(&v);
16//! assert_eq!(result, vec![1, 3]);
17//! ```
18
19#[fp_macros::document_module]
20mod inner {
21 use {
22 crate::kinds::*,
23 fp_macros::*,
24 };
25
26 /// A type class for data structures that can be compacted and separated by reference.
27 ///
28 /// Like [`Compactable`](crate::classes::Compactable), but takes the container by reference
29 /// (`&F<Option<A>>`) instead of by value. Because elements must be extracted from a
30 /// borrowed container, the element types require [`Clone`].
31 ///
32 /// ### Laws
33 ///
34 /// The same laws as [`Compactable`](crate::classes::Compactable) apply;
35 /// `ref_compact` and `ref_separate` must agree with their by-value counterparts
36 /// when applied to cloned inputs.
37 #[document_examples]
38 ///
39 /// ```
40 /// use fp_library::{
41 /// brands::*,
42 /// functions::explicit::*,
43 /// };
44 ///
45 /// let v = vec![Some(1), None, Some(3)];
46 /// let result = compact::<VecBrand, _, _, _>(&v);
47 /// assert_eq!(result, vec![1, 3]);
48 ///
49 /// let v2: Vec<Result<i32, &str>> = vec![Ok(1), Err("bad"), Ok(3)];
50 /// let (errs, oks) = separate::<VecBrand, _, _, _, _>(&v2);
51 /// assert_eq!(oks, vec![1, 3]);
52 /// assert_eq!(errs, vec!["bad"]);
53 /// ```
54 #[kind(type Of<'a, A: 'a>: 'a;)]
55 pub trait RefCompactable {
56 /// Compacts a borrowed data structure of [`Option`]s, discarding [`None`] values and cloning [`Some`] values.
57 #[document_signature]
58 ///
59 #[document_type_parameters(
60 "The lifetime of the elements.",
61 "The type of the elements in the [`Option`]. Must be [`Clone`] because elements are extracted from a borrowed container."
62 )]
63 ///
64 #[document_parameters("A reference to the data structure containing [`Option`] values.")]
65 ///
66 #[document_returns(
67 "A new data structure containing only the cloned values from the [`Some`] variants."
68 )]
69 #[document_examples]
70 ///
71 /// ```
72 /// use fp_library::{
73 /// brands::*,
74 /// functions::explicit::*,
75 /// };
76 ///
77 /// let v = vec![Some(1), None, Some(3)];
78 /// let result = compact::<VecBrand, _, _, _>(&v);
79 /// assert_eq!(result, vec![1, 3]);
80 ///
81 /// let v2 = vec![None::<i32>, None, None];
82 /// let result2 = compact::<VecBrand, _, _, _>(&v2);
83 /// assert_eq!(result2, Vec::<i32>::new());
84 /// ```
85 fn ref_compact<'a, A: 'a + Clone>(
86 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<A>>)
87 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>);
88
89 /// Separates a borrowed data structure of [`Result`]s into two data structures: one containing the cloned [`Err`] values and one containing the cloned [`Ok`] values.
90 #[document_signature]
91 ///
92 #[document_type_parameters(
93 "The lifetime of the elements.",
94 "The type of the error values. Must be [`Clone`] because elements are extracted from a borrowed container.",
95 "The type of the success values. Must be [`Clone`] because elements are extracted from a borrowed container."
96 )]
97 ///
98 #[document_parameters("A reference to the data structure containing [`Result`] values.")]
99 ///
100 #[document_returns(
101 "A pair of data structures: the first containing the cloned [`Err`] values, and the second containing the cloned [`Ok`] values."
102 )]
103 #[document_examples]
104 ///
105 /// ```
106 /// use fp_library::{
107 /// brands::*,
108 /// functions::explicit::*,
109 /// };
110 ///
111 /// let v: Vec<Result<i32, &str>> = vec![Ok(1), Err("bad"), Ok(3)];
112 /// let (errs, oks) = separate::<VecBrand, _, _, _, _>(&v);
113 /// assert_eq!(oks, vec![1, 3]);
114 /// assert_eq!(errs, vec!["bad"]);
115 /// ```
116 fn ref_separate<'a, E: 'a + Clone, O: 'a + Clone>(
117 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
118 ) -> (
119 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
120 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
121 );
122 }
123
124 /// Compacts a borrowed data structure of [`Option`]s, discarding [`None`] values and cloning [`Some`] values.
125 ///
126 /// Free function version that dispatches to [the type class' associated function][`RefCompactable::ref_compact`].
127 #[document_signature]
128 ///
129 #[document_type_parameters(
130 "The lifetime of the elements.",
131 "The brand of the compactable structure.",
132 "The type of the elements in the [`Option`]. Must be [`Clone`] because elements are extracted from a borrowed container."
133 )]
134 ///
135 #[document_parameters("A reference to the data structure containing [`Option`] values.")]
136 ///
137 #[document_returns(
138 "A new data structure containing only the cloned values from the [`Some`] variants."
139 )]
140 #[document_examples]
141 ///
142 /// ```
143 /// use fp_library::{
144 /// brands::*,
145 /// functions::explicit::*,
146 /// };
147 ///
148 /// let v = vec![Some(1), None, Some(3)];
149 /// let result = compact::<VecBrand, _, _, _>(&v);
150 /// assert_eq!(result, vec![1, 3]);
151 /// ```
152 pub fn ref_compact<'a, Brand: RefCompactable, A: 'a + Clone>(
153 fa: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<A>>)
154 ) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
155 Brand::ref_compact(fa)
156 }
157
158 /// Separates a borrowed data structure of [`Result`]s into two data structures: one containing the cloned [`Err`] values and one containing the cloned [`Ok`] values.
159 ///
160 /// Free function version that dispatches to [the type class' associated function][`RefCompactable::ref_separate`].
161 #[document_signature]
162 ///
163 #[document_type_parameters(
164 "The lifetime of the elements.",
165 "The brand of the compactable structure.",
166 "The type of the error values. Must be [`Clone`] because elements are extracted from a borrowed container.",
167 "The type of the success values. Must be [`Clone`] because elements are extracted from a borrowed container."
168 )]
169 ///
170 #[document_parameters("A reference to the data structure containing [`Result`] values.")]
171 ///
172 #[document_returns(
173 "A pair of data structures: the first containing the cloned [`Err`] values, and the second containing the cloned [`Ok`] values."
174 )]
175 #[document_examples]
176 ///
177 /// ```
178 /// use fp_library::{
179 /// brands::*,
180 /// functions::explicit::*,
181 /// };
182 ///
183 /// let v: Vec<Result<i32, &str>> = vec![Ok(1), Err("bad"), Ok(3)];
184 /// let (errs, oks) = separate::<VecBrand, _, _, _, _>(&v);
185 /// assert_eq!(oks, vec![1, 3]);
186 /// assert_eq!(errs, vec!["bad"]);
187 /// ```
188 pub fn ref_separate<'a, Brand: RefCompactable, E: 'a + Clone, O: 'a + Clone>(
189 fa: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
190 ) -> (
191 Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
192 Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
193 ) {
194 Brand::ref_separate::<E, O>(fa)
195 }
196}
197
198pub use inner::*;