hetseq/fold.rs
1use {List, Queue};
2
3#[cfg(not(feature="nightly"))]
4use HetFnMut as FnMut;
5
6/// Foldable heterogenous list
7///
8/// # Example
9/// ```rust
10/// #![cfg_attr(feature="nightly", feature(unsize, fn_traits, unboxed_closures))]
11/// #[macro_use]
12/// extern crate hetseq;
13///
14/// use hetseq::{Foldable, Functor, Queue};
15/// #[cfg(not(feature="nightly"))]
16/// use hetseq::prelude::*;
17///
18/// use std::fmt::Display;
19/// lambda![ let Formatter = |arg: Display| -> String { format!("{}", arg) } ];
20/// lambda![
21/// let Extender = |item, extend: Extend<item>| -> extend {
22/// extend.extend(::std::iter::once(item));
23/// extend
24/// }
25/// ];
26/// fn main() {
27/// let queue = hqueue![1, 2.5];
28/// let strings = queue.fmap(&Formatter).fold(Vec::new(), &Extender);
29/// assert_eq!(strings, ["1", "2.5"]);
30/// }
31/// ```
32pub trait Foldable<I, F> {
33 /// fold sequence using `F`unction starting with `I`nit value
34 fn fold(self, init: I, f: F) -> I;
35}
36
37impl<I, F> Foldable<I, F> for List<()> {
38 fn fold(self, init: I, _: F) -> I { init }
39}
40
41impl<I, F> Foldable<I, F> for Queue<()> {
42 fn fold(self, init: I, _: F) -> I { init }
43}
44
45impl<I, F, H, T> Foldable<I, F> for List<(H, T)>
46 where T: Foldable<I, F>,
47 F: FnMut<(H, I), Output=I>
48{
49 fn fold(self, init: I, mut f: F) -> I {
50 let List((head, tail)) = self;
51 tail.fold(f.call_mut((head, init)), f)
52 }
53}
54
55impl<I, F, H, T> Foldable<I, F> for Queue<(H, T)>
56 where H: for<'a> Foldable<I, &'a mut F>,
57 F: FnMut<(T, I), Output=I>
58{
59 fn fold(self, init: I, mut f: F) -> I {
60 let Queue((head, tail)) = self;
61 let head = head.fold(init, &mut f);
62 f.call_mut((tail, head))
63 }
64}
65