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