I have an array of ordered enumerables IorderedEnumerable and I want to flatten it so that the ordered enumerables of foo are concat
All LINQ to Objects methods (except, obviously, OrderBy() and ToDictionary()) will preserve source ordering.
Lists (represented by IEnumerable<T> in .net) along with two operations form a monad, which must obay the monad laws. These two operations are given different names in different languages, the wikipedia article uses Haskell which calls them return and >>= (called 'bind'). C# calls >>= SelectMany and does not have a built-in function for return. The names are unimportant however and what matters is the types. Specialised for IEnumerable<T> these are:
Return :: T -> IEnumerable<T>
SelectMany :: IEnumerable<T> -> Func<T, IEnumerable<U>> -> IEnumerable<U>
Return simply returns a 1-element sequence containing the given element e.g.
public static IEnumerable<T> Return<T>(T item)
{
return new[] { item };
}
SelectMany is already implemented as Enumerable.SelectMany:
public static IEnumerable<U> SelectMany<T, U>(IEnumerable<T> seq, Func<T, IEnumerable<U>> f) { ... }
SelectMany takes an input sequence and a function which generates another sequence for each item of the input sequence and flattens the resulting sequence of sequences into one.
Restating the first two monad laws in C# we have:
Left identity
Func<T, IEnumerable<U>> f = ...
Return(x).SelectMany(f) == f(x)
Right identity
IEnumerable<T> seq = ...
seq.SelectMany(Return) == seq
By the right identity law, SelectMany must flatten each sequence generated by the Func<T, IEnumerable<U>> according to the order of the input elements.
Assume it flattened them in reverse order e.g.
new[] { 1, 2 }.SelectMany(i => new[] { i, -i }) == new[] { 2, -2, 1, -1 }
then
var s = new[] { 1, 2 }
s.SelectMany(Return) == new[] { 2, 1 } != s
which would not satisfy the right-identity law required.