Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ SelectMany is bind?

Tags:

c#

linq

SelectMany will traverse an object tree:

class Agency { List<Employees> Staff }

IEnumerable<Agency> Agencies

IEnumerable<Employee> =  
from anAgency in Agencies  
from anEmployee in anAgency.Staff. 
select anEmployee; 

Usually, i would always pick an Agency first, and use the internal instance of Staff to get the employees. But in the case of a government shutdown, I just want to list EVERYBODY to see who can cover.

In this rare case which is inappropriate for my object model, i can use SelectMany to arbitrarily traverse the tree.

What do you call this traversal? a cross join?  It isn't because the joining is already implicit in the composition of the Staff in the Agency object.

Is it bind? I don't know anything about bind.

Has it no other name than Select, Many ?!

like image 762
Andyz Smith Avatar asked Oct 11 '13 15:10

Andyz Smith


People also ask

What does SelectMany do in Linq?

The SelectMany in LINQ is used to project each element of a sequence to an IEnumerable<T> and then flatten the resulting sequences into one sequence. That means the SelectMany operator combines the records from a sequence of results and then converts it into one result.

What is the use of SelectMany?

The SelectMany() method is used to "flatten" a sequence in which each of the elements of the sequence is a separate, subordinate sequence.

What is the difference between select and SelectMany in Linq?

Select and SelectMany are projection operators. A select operator is used to select value from a collection and SelectMany operator is used to selecting values from a collection of collection i.e. nested collection.

Is Linq a Monad?

LINQ is monad. It is very carefully designed by Erik Meijer so that it is monad.


Video Answer


2 Answers

SelectMany in C# corresponds to bind in Haskell (>>=) or flatMap in Scala. The signature of >>= in Haskell is:

(>>=) :: Monad m => m a -> (a -> m b) -> m b

so bind is an operation used to construct one monadic value from another.

In the case of C# m in the above signature is IEnumerable, IObservable, IQueryable etc. For IEnumerable, SelectMany is therefore

IEnumerable<A> -> (A -> IEnumerable<B>) -> IEnumerable<B>

or in C#

public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> first, Func<A, IEnumerable<B>> selector)

The meaning of bind depends on the monad type, for IEnumerable, each element in the input sequence is used to create a new sequence, and the resulting sequence of sequences is flattened to produce the output sequence.

There is another formulation of bind which may make this more clear. While monads are often described in terms of their implementation of bind, monads must also support two other operations, map and join.

map corresponds to Select in C# and looks like:

map :: Monad m => (a -> b) -> (ma -> m b)

so it is a 'structure preserving' way of lifting a regular function over a monadic value.

join has the type

join :: Monad m => m m a -> m a

so join is used to flatten nested monadic values. In C# this would look like

public static IEnumerable<A> Join<A>(this IEnumerable<IEnumerable<A>> nested)

bind can be implemented in terms of map and join as

m >>= f = join (map f m)

so to answer the original question, SelectMany corresponds to bind or flatMap in other languages. Bind is not just flattening, but can be seen as a transformation followed by a flattening of nested monadic values (e.g. sequences in the case of IEnumerable<T>). join for IEnumerable<T> does not exist in the current linq extensions.

like image 126
Lee Avatar answered Sep 27 '22 20:09

Lee


Out of .NET world it's often called "flattening", if that's what you're asking. It flattens a two-dimensional result set into a single dimension.

like image 26
Dan Avatar answered Sep 27 '22 21:09

Dan