Skip to content

Commit 094bc95

Browse files
committed
Separate the 2 variants, consuming and non-consuming
1 parent bb60bea commit 094bc95

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

src/coproduct.rs

+38-31
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@
3333
//! # let co2: I32Bool = into_coproduct(true);
3434
//!
3535
//! let folder = hlist![
36-
//! |i| format!("i32 {}", i),
37-
//! |b| String::from(if b { "t" } else { "f" })
36+
//! |&i| format!("i32 {}", i),
37+
//! |&b| String::from(if b { "t" } else { "f" })
3838
//! ];
3939
//!
40-
//! assert_eq!(co1.fold(&folder), "i32 3".to_string());
41-
//! assert_eq!(co2.fold(&folder), "t".to_string());
40+
//! assert_eq!(co1.as_ref().fold(&folder), "i32 3".to_string());
41+
//! assert_eq!(co2.as_ref().fold(&folder), "t".to_string());
42+
//!
43+
//! // There is also a value consuming-variant of fold
44+
//!
45+
//! let folded = co1.fold(hlist![
46+
//! |i| format!("i32 {}", i),
47+
//! |b| String::from(if b { "t" } else { "f" })
48+
//! ]);
49+
//! assert_eq!(folded, "i32 3".to_string());
4250
//! # }
4351
//! ```
4452
@@ -200,63 +208,63 @@ impl<Head, FromTail, Tail, TailIndex> CoproductSelector<FromTail, There<TailInde
200208
/// let co2: I32StrBool = into_coproduct(true);
201209
/// let co3: I32StrBool = into_coproduct(42f32);
202210
///
203-
/// let folder = hlist![|i| format!("int {}", i),
204-
/// |f| format!("float {}", f),
205-
/// |b| (if b { "t" } else { "f" }).to_string()];
211+
/// let folder = hlist![|&i| format!("int {}", i),
212+
/// |&f| format!("float {}", f),
213+
/// |&b| (if b { "t" } else { "f" }).to_string()];
206214
///
207-
/// assert_eq!(co1.fold(&folder), "int 3".to_string());
208-
/// assert_eq!(co2.fold(&folder), "t".to_string());
209-
/// assert_eq!(co3.fold(&folder), "float 42".to_string());
215+
/// assert_eq!(co1.as_ref().fold(&folder), "int 3".to_string());
216+
/// assert_eq!(co2.as_ref().fold(&folder), "t".to_string());
217+
/// assert_eq!(co3.as_ref().fold(&folder), "float 42".to_string());
210218
/// # }
211219
/// ```
212220
pub trait CoproductFoldable<Folder, Output> {
213-
fn fold(self, f: &Folder) -> Output;
221+
fn fold(self, f: Folder) -> Output;
214222
}
215223

216224
impl<F, R, FTail, CH, CTail> CoproductFoldable<HCons<F, FTail>, R> for Coproduct<CH, CTail>
217-
where F: Fn(CH) -> R,
225+
where F: FnOnce(CH) -> R,
218226
CTail: CoproductFoldable<FTail, R>
219227
{
220-
fn fold(self, f: &HCons<F, FTail>) -> R {
228+
fn fold(self, f: HCons<F, FTail>) -> R {
221229
use self::Coproduct::*;
222-
let ref f_head = f.head;
223-
let ref f_tail = f.tail;
230+
let f_head = f.head;
231+
let f_tail = f.tail;
224232
match self {
225233
Inl(r) => (f_head)(r),
226234
Inr(rest) => rest.fold(f_tail),
227235
}
228236
}
229237
}
230238

231-
impl<'a, F, R, FTail, CH, CTail> CoproductFoldable<HCons<F, FTail>, R> for &'a Coproduct<CH, CTail>
239+
impl<'a, F, R, FTail, CH, CTail> CoproductFoldable<&'a HCons<F, FTail>, R> for &'a Coproduct<CH, CTail>
232240
where F: Fn(&'a CH) -> R,
233241
CTail: 'a,
234242
FTail: 'a,
235-
&'a CTail: CoproductFoldable<FTail, R>
243+
&'a CTail: CoproductFoldable<&'a FTail, R>
236244
{
237-
fn fold(self, f: &HCons<F, FTail>) -> R {
245+
fn fold(self, f: &'a HCons<F, FTail>) -> R {
238246
use self::Coproduct::*;
239247
let ref f_head = f.head;
240248
let ref f_tail = f.tail;
241249
match *self {
242250
Inl(ref r) => (f_head)(r),
243-
Inr(ref rest) => <&'a CTail as CoproductFoldable<FTail, R>>::fold(rest, f_tail),
251+
Inr(ref rest) => <&'a CTail as CoproductFoldable<&'a FTail, R>>::fold(rest, f_tail),
244252
}
245253
}
246254
}
247255

248256
/// This is literally impossible; CNil is not instantiable
249257
#[doc(hidden)]
250258
impl<F, R> CoproductFoldable<F, R> for CNil {
251-
fn fold(self, _: &F) -> R {
259+
fn fold(self, _: F) -> R {
252260
unreachable!()
253261
}
254262
}
255263

256264
/// This is literally impossible; &CNil is not instantiable
257265
#[doc(hidden)]
258-
impl<'a, F, R> CoproductFoldable<F, R> for &'a CNil {
259-
fn fold(self, _: &F) -> R {
266+
impl<'a, F, R> CoproductFoldable<&'a F, R> for &'a CNil {
267+
fn fold(self, _: &'a F) -> R {
260268
unreachable!()
261269
}
262270
}
@@ -297,28 +305,27 @@ mod tests {
297305
type I32StrBool = Coproduct!(i32, f32, bool);
298306

299307
let co1: I32StrBool = into_coproduct(3);
300-
let co2: I32StrBool = into_coproduct(true);
301-
let co3: I32StrBool = into_coproduct(42f32);
308+
let folded = co1.fold(hlist![|i| format!("int {}", i),
309+
|f| format!("float {}", f),
310+
|b| (if b { "t" } else { "f" }).to_string()]);
302311

303-
let folder = hlist![|i| format!("int {}", i),
304-
|f| format!("float {}", f),
305-
|b| (if b { "t" } else { "f" }).to_string()];
306-
307-
assert_eq!(co1.fold(&folder), "int 3".to_string());
308-
assert_eq!(co2.fold(&folder), "t".to_string());
309-
assert_eq!(co3.fold(&folder), "float 42".to_string());
312+
assert_eq!(folded, "int 3".to_string());
310313
}
311314

312315
#[test]
313316
fn test_coproduct_fold_non_consuming() {
314317
type I32StrBool = Coproduct!(i32, f32, bool);
315318

316319
let co1: I32StrBool = into_coproduct(3);
320+
let co2: I32StrBool = into_coproduct(true);
321+
let co3: I32StrBool = into_coproduct(42f32);
317322

318323
let folder = hlist![|&i| format!("int {}", i),
319324
|&f| format!("float {}", f),
320325
|&b| (if b { "t" } else { "f" }).to_string()];
321326

322327
assert_eq!(co1.as_ref().fold(&folder), "int 3".to_string());
328+
assert_eq!(co2.as_ref().fold(&folder), "t".to_string());
329+
assert_eq!(co3.as_ref().fold(&folder), "float 42".to_string());
323330
}
324331
}

0 commit comments

Comments
 (0)