title: F# Railway Programming is this initialization can be improved?
body: <p>I'm learning F# and I wonder if this method implementation which initializes first N elements of an array could be improved. At the moment it works perfectly fine. I mean if it fails when it attempts to initialize 2nd element by performing 2nd call to the factory, then if would call undo for the first successful result. The only minor problem it doesn't clean items in the array if error, but I do not worry about it. All I worry is that it should do undo for the first successful results if it fails on 2nd or 3rd or later. If it succeeds then success result should have in Undo list all the functors to do undo.</p>
  
  <p>The thing is that I'd like to avoid recursion and use something like Linq to iterate and do stuff, but it is not clear how to do let with bang(let!) in that case</p>
  
  <pre class="lang-ml prettyprint-override"><code>// val private initializeArrayInternal: 
  //    arr    : 'a option [] -&gt;
  //    factory: unit -&gt; RopWithUndo.Result&lt;'a&gt; -&gt;
  //    count  : int          -&gt;
  //    index  : int          
  //          -&gt; RopWithUndo.Result&lt;'a option []&gt;
  let rec private initializeArrayInternal (arr: _ []) factory count index =
      if (arr.GetLength(0) &lt; count) then 
          rwu.Failure "Count can not be greater than array length"
      else if (count = index ) then
          rwu.successNoUndo arr
      else 
          rwu.either {        
              let! element = factory()
              arr.[index] &lt;- Some element 
              return (initializeArrayInternal arr factory count (index+1))
          }
  
  
  // val initializeArray: 
  //    arr    : 'a option [] -&gt;
  //    factory: unit -&gt; RopWithUndo.Result&lt;'a&gt; -&gt;
  //    count  : int          
  //          -&gt; RopWithUndo.Result&lt;'a option []&gt;        
  let rec initializeArray arr factory count =
      initializeArrayInternal arr factory count 0 
  
  </code></pre>
  
  <p>RopWinUndo</p>
  
  <pre class="lang-ml prettyprint-override"><code>module RopWithUndo
  
  type Undo = unit -&gt; unit
  
  type Result&lt;'success&gt; =
      | Success of 'success * Undo list
      | Failure of string
  
  /// success with empty Undo list. It only applies to the curretn operation. The final list is concatenated of all list and no problem if some lists are empty.
  let successNoUndo result =
      Success (result,[])
  
  let doUndo undoList =
      undoList |&gt; List.rev |&gt; List.iter (fun undo -&gt; undo())
  
  let bind f x =
      match x with
      | Failure e -&gt; Failure e 
      | Success (s1,undoList1) -&gt;            
          try
              match f s1 with
              | Failure e -&gt;
                  // undo everything in reverse order 
                  doUndo undoList1
                  // return the error
                  Failure e 
              | Success (s2,undoList2) -&gt;
                  // concatenate the undo lists
                  Success (s2, undoList1 @ undoList2)
          with
          | _ -&gt; 
              doUndo undoList1
              reraise()
  
  type EitherBuilder () =
      member this.Bind(x, f) = bind f x
  
      member this.ReturnFrom x = x
      member this.Return x = x
      member this.Delay(f) = f()
  
  let either = EitherBuilder ()
  
  </code></pre>