Generally you need to interact with language.Ext types, they are generally containers that er, contain things. They are actually called Monads, as I mentioned in Using Language Ext but lets stick to them just being containers with items in them. in most cases you need to extract the item to work with it. So here are some key ideas:
 
To Iterate is to 'extract' item from container.

A Container is IEnumerable<T> or Either<T1,T2> or loosely any type that contains other things...

The Select() and SelectMany() functions in Linq all extract/iterate an item-at-a-time from the provided container before proceeding further.

It runs a user provided function on it each extracted item and puts the result into a new container. If no items, it puts nothing into the container and a empty container is produced

The function is either a non-container producing function, usually named map() or a container-producing function usually called bind(). Both functions transform their input so effectively apart from how they return it, they do the same type of job - transformation.

The result of the scalar function is put into a new container either automatically by the Select/Map() functions for explicitly if you use Bind().

The result of the monad-producing function ie bind() is further extracted and that's put in the new container. If no result, nothing or None/Bad/ ndicating value put int Container

Short story:

  1. Extract item from container,
  2. Inspect the item to see it exists or is valid
  3. If so(valid):
    1. if scalar function, execute scalar function and return scalar result into new container,
    2. if monad-producing function ie bind(), execute it and if any items in continer extract items from container and put into new container.
  1. An item extracted from an IEnumerable<T> is extracted via the foreach Operator.
  2. An item extracted from an Option<T> is extracted via Match() or Linq Select synatax
Side note:
  • Whenever a None appears in the LINQ expression the final result will always be None. This is the shortcut for if (this will be shown later)

Eg:

Bind function attempts to run a monad-producing function on each item it can extract from the container. If it cannot extract the item, it doesn't run the function. Each item is extracted from that monad-producing function ie bind and returned.

public static Option<TOUT> Bind<TIN,TOUT>( this Option<TIN> self, // Container
                                           Func<TIN, Option<OUT> bind // Container producing function
                                         )
=> self.Match(  // A) extract item from container 
                // and check its validity...
         Some: a => bind(a), // B) If item valid (in this case just being 
                             // a SOME makes it valid), run container-producing function
                             // bind() on item which will return another Container
         None: () => None // If could not extract item or the extracted item
                          // is not valid, return Container of None
    )

For Either<L,R>:

/* Bind runs a container producing function */
public static Either<L,R2> Bind<L, R1>( this Either<L,R1> self, // Takes in a container of Either<L, R1>
                                        Func<R1, Either<L,R2> bind // Takes a container producing function
                                      )
=> self.Match(  // extract item from container
                // and verify item
         Right: r => bind(r),  // if its a right item, its OK, run the container-producing function 
                // that in turn returns a container for next bind() if there is one...
         Left: () => Left // if its a left, don't do container-producing function, just return left again..
         )

Each time a Bind() encounters a Left in the container, it returns a left. If the container, in this case, is an instance of Either<Left, Right> but contains a left value: 

 result = Container.Bind(me_not_run()) // Container determined to not have right(correct), so return LEFT
 Container.Bind(me_not_run_either()) // Container determined to be left(wrong), so return LEFT
 Container.Bind(me_not_run_neither()) // Container determined to be left(wrong), so return LEFT

And Consequently never runs the user container producing function in this case…the resulting container is just a container with a Left in it that cascades all the way down and ultimately the result is a Container of Left.

 Container1
      // Attempt to extract item from Container1 and run container-producing function 
      // on it. Return the extracted item from container or 
      // indicate NotFound be returning Left
     .Bind( item => { /* container producing function which return Container.
           internally if extracted, returns each member of container otherwise Returns 
              Container<None/Left> /*  }
     .Bind( item => { ret Container} ) // Else Container<None/Left/Blank>
     // If Has Item Of required (any Right)
     .Bind( item => { do something on it and return Container} // else Container<None/Left>
 
     // Whats hidden if HOW we extract the item, and what container to return 
     // if the item was not found or correct. Otherwise just return items 
     // from container produced from container-producing function

Bind's Story:

If the Container has the required value(or simple criteria of any specific value) then Get it and run a container-producing function on it.

If the Container doesn't, don't run the function and return a Blank/NotFound Container.

Plan your conditional code like this:

if(ContainerHasOKItem) {
 // Your Ok Code which works with the OK Item and produces another Container 
 // for next Bind() to interrogate for OKness.
} else {
 // Internal/Hidden code returns Container<BAD> for next Bind() to integorate for OKness.
}

which corresponds to the functional notation of: 

  Container.Bind(item=> me) // if my container has a valid item or state, run me() 
                            // on the item or state. me() will return a container
            .Bind(item => me) // this is the next bind which will re-check the 
                              // container for a valid item or state etc..
            .Bind(item => me)
// Internally Bind() checks if the container has Good or Bad value in it,if it has 
// bad it returns Container<Bad> otherwise if returns your 
// container producing function (which could container a good or 
// bad value based on if your function said it should)
ContainerA
.Bind(containerA_has_ok_so_run_my_ok_func) // Produces a Container, Bind() then
// inspects it - returns Container<Bad> or passed Good to my_func
.Bind(containerA_has_ok_so_run_my_ok_func2) // Produces a Container ...
.Bind(containerA_has_ok_so_run_my_ok_func​​​​​​​3) // Produces a Container ...​

Note: The determination of what is a required value for the container to have, for the monad-producing() function to be called is within specified/coded within the Bind extension method.

So with all this being said the underlying ideas are essentially this:

  1. Extract an item from the container
  2. Verify the extracted item or state of container is suitable and run monad-producing function on it.
  3. If the container or the item extracted from it is undesirable then return Container indicating bad item/state.

Something like this hopefully demonstrates it:

 

 

How much does your brain hurt now?

Side notes:

 Do your IO and first then pass in immutable results of the IO into pure functions. Push as much Io to the fringes and as the hierchy goes down use more and more pure functions

Option<T> captures if behavior IEnumerable<T> captures foreach behavior Select/Map make types into functors Functors allow you to use regular functions(Fn()) with types that contain or amplify other types (T<A>): T<A>.Map(Fn()) Map is a Select which is a way to remove the boilder place code of a foreach Bind is a SelectMany without the project function. Bind() is a function that does the binding of one Monad to another