For reduce it's not even necessary for the aggregate type to be the same as the type used by the list. Want to concatenate a list of integers together as a string? You can!
public delegate TAggregate ReduceDelegate<TAggregate, TInput>(TAggregate aggregate, TInput input);
public static TAggregate Reduce<TAggregate, TInput>(IEnumerable<TInput> list, TAggregate initial, ReduceDelegate<TAggregate, TInput> function)
{
TAggregate aggregate = initial;
foreach( TInput item in list )
aggregate = function(aggregate, item);
return aggregate;
}
public static void Foo()
{
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
string concat = Reduce(list, "", delegate(string aggregate, int input) { return aggregate + input.ToString(); });
}
The result will be "123".

EDIT:
Prefer to do the concatenation with a stringbuilder? Also possible:
string concat = Reduce(list, new StringBuilder(), delegate(StringBuilder aggregate, int input) { return aggregate.Append(input.ToString()); }).ToString();
