Sunday, September 26, 2010

F# Computation Expression Bind/Return Mechanics Continued.

Isn’t it always the way? Almost as soon as I posted the previous entry, I came up with an example I like better. Rather than replace that example, I’ll just post the new one here.

This one adds overloads to Bind, which show how both multiple types of let! bindings as well as do! bindings can be produced. It prints a trace of the calls and returns to the console, illustrating the descend an return behavior.

Below are the output and the code. As always, it is presented "as-is" and without warranty or implied fitness of any kind; use at your own risk.



 
/// Sample do!,let!,return! binder.
type Binder () =
 
  /// For indent to list level.
  let rec spaces spc = function
    | [] -> spc
    | h::t -> spaces ("  "+spc) t
 
  /// let! binding (first use).
  member this.Bind (s:string,
                    f:string list->string list) =
    printfn "Entering let! %s,[]" s
    let rtn = List.tail (f [s])
    printfn "%sLeaving let! %s,%A" (spaces "" rtn) s rtn
    rtn
 
  /// let! binding (nth use).
  member this.Bind ((s,sl):string*(string list),
                    f:string list->string list) =
    printfn "%sEntering let! %s,%A" (spaces "" sl) s sl
    let rtn = List.tail (f (s::sl))
    printfn "%sLeaving let! %s,%A" (spaces "" rtn) s rtn
    rtn
 
  /// do! binding.
  member this.Bind ((s,sl):string*(string list),
                    f:unit->string list) =
    printfn "%sEntering do! %s,%A" (spaces "" sl) s sl
    let rtn = f()
    printfn "%sLeaving do! %s,%A" (spaces "" rtn) s rtn
    rtn
 
  /// return.
  member this.Return (a:string list) =
    printfn "%sReturn %A" (spaces "" a) a
    a
 
 
// Test.
let result = Binder () {
   let! x = "A"
   let! x = "B",x
   do! "B0",x
   let! x = "C",x
   return x }  
 
printfn "Your breakpoint here."
 


p.s. For the spaces function you could also use something like:
new string(' ',sl.Length*2)

No comments: