Generic abstractions for combining and nesting reduction patterns for iterables.

The main entry point to this library is Reduce::reduce_with, which can be called on any Iterator, and is very similar to Iterator::reduce, but uses a generic implementation of a Reductor for the reduction logic.

The following examples shows some of the basic building blocks from which reductor enables building more complex patterns:

```rust use reductor::{Reduce, Sum, Product, Count, Min, Max};

let iter = 0..10;

let Sum(sum) = iter.clone().reducewith::>(); let Product(product) = iter.clone().reducewith::>(); let Count(count) = iter.clone().reducewith(); asserteq!(sum, iter.clone().sum()); asserteq!(product, iter.clone().product()); asserteq!(count, iter.clone().count());

let Max(max) = iter.clone().reducewith::>>(); let Min(min) = iter.clone().reducewith::>>(); asserteq!(max, Some(9)); asserteq!(min, Some(0)); ```

Notice that unlike Sum and Product, Min and Max won't reduce an empty iterator into the default value. This mirrors the way Iterator::max returns an Option<T>, unlike Iterator::sum.

Now, let's combine two Reductors to reduce an iterator that produces a pair of values:

```rust use reductor::{Reduce, Sum, Product};

let iter = 0..10; let (Sum(sum), Product(product)) = iter .clone() .map(|x| (x, x * 2)) .reduce_with::<(Sum, Product)>();

asserteq!(sum, iter.clone().sum()); asserteq!(product, iter.map(|x| x * 2).product()); ```

Another abstraction provided by this library is ReductorPair, which allows reducing an iterator producing a single value by a pair of Reductors, in tandem.

```rust use reductor::{Reduce, ReductorPair, Sum, Max};

let iter = 0..10; let ReductorPair(Max(max), Sum(sum)) = iter .clone() .map(|x| x) .reduce_with::, Sum>>>().unwrap();

asserteq!(sum, iter.clone().sum()); asserteq!(max, iter.clone().max().unwrap()); ```

These constructs allow building very complex iterator loops that compose numerous reductions into a single set of results.

```rust use reductor::{Reduce, ReductorPair, Count, Sum, Product, Max, Min};

let iter = (0i32..100).filtermap(|x| { if x % 2 == 0 { None } else { Some((x, x.leading_zeros())) } });

let ReductorPair(Count(count), (Sum(sum), ReductorPair(Min(min), Max(max)))) = iter .clone() .reduce_with::, ReductorPair, Max>)>>>().unwrap();

asserteq!(count, iter.clone().count()); asserteq!(sum, iter.clone().map(|(x, ..)| x).sum()); asserteq!(min, iter.clone().map(|(.., x)| x).min().unwrap()); asserteq!(max, iter.map(|(.., x)| x).max().unwrap()); ```