1 people like it.
    Like the snippet!
  
  Monad Bind 3 of 3
  After watching this clip (http://www.youtube.com/watch?v=ZhuHCtR3xq8) on Youtube featuring Brian Beckman I wanted to try to sketch Brian's main argument that Monads' main purpose is function composition.
I will post my sketch to http://rodhern.wordpress.com/2014/02/ .
These snippets are the companion examples to the blog post.
  
| 1: 
2: 
 | // Script example (3 of 3) for Monad blog post
// at http://rodhern.wordpress.com/2014/02/
 | 
|  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
 | type M<'V> =
     {
       Value: 'V
       LogMessages: string list
     }
     with
      static member StaticReturn v = { Value= v; LogMessages= [] }
      static member StaticBind (mt: M<'a>) (fn: 'a -> M<'b>) =
              let result = fn mt.Value
              let newmessage = sprintf ("Passing value %+A") mt.Value
              let logmessages = result.LogMessages @ (newmessage :: mt.LogMessages)
              { Value= result.Value; LogMessages= logmessages }
 | 
|  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
 | /// A shorter name for M.StaticReturn.
/// Turning a variable of type 'a into M<'a> .
let ret x = M<_>.StaticReturn x
/// Turning a function with signature 'a -> 'b  into  M<'a> -> M<'b> .
let package fn mt = M<_>.StaticBind mt (fn >> ret)
/// The builder type may be an empty class like this one.
/// Often the builder instance is really nothing more than
/// a syntactic requirement.
type ComputationExpressionBuilderType () =
      member public self.Return v = M<_>.StaticReturn v
      member public self.Bind (mt, fn) = M<_>.StaticBind mt fn
 | 
| 1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
 | type A = int       
type B = float     
type C = DateTime  
type D = string    
type R = M<A>
type S = M<B>
type T = M<C>
type U = M<D>
 | 
| 1: 
2: 
3: 
 | let f (noWeeks: A): B = float (7 * noWeeks)
let g (noDays: B): C = today.AddDays noDays
let h (date: C): D = date.ToShortDateString ()
 | 
| 1: 
2: 
3: 
 | let pf: R -> S = package f
let pg: S -> T = package g
let ph: T -> U = package h
 | 
| 1: 
2: 
 | let fghOne: R -> U = compose(compose(pf, pg), ph)
let fghTwo: R -> U = compose(pf, compose(pg, ph))
 | 
| 1: 
2: 
 | let fghOneResult = fghOne (ret myInputParam)
let fghTwoResult = fghTwo (ret myInputParam)
 | 
| 1: 
2: 
3: 
4: 
 | let Mx: R = ret myInputParam
let Mf: A -> S = f >> M<_>.StaticReturn
let Mg: B -> T = g >> M<_>.StaticReturn
let Mh: C -> U = h >> M<_>.StaticReturn
 | 
|  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
 | let builder = new ComputationExpressionBuilderType ()
let result =
    builder {
              let! a = Mx
              let! b = Mf a
              let! c = Mg b
              let! d = Mh c
              return d
            }
 | 
type M<'V> =
  {Value: 'V;
   LogMessages: string list;}
  static member StaticBind : mt:M<'a> -> fn:('a -> M<'b>) -> M<'b>
  static member StaticReturn : v:'a -> M<'a>
Full name: Script.M<_>
 In this example, as is often the case, the Monad, M<'V>,
 is a container for, 'V, the value if interest.
M.Value: 'V
M.LogMessages: string list
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
static member M.StaticReturn : v:'a -> M<'a>
Full name: Script.M`1.StaticReturn
val v : 'a
static member M.StaticBind : mt:M<'a> -> fn:('a -> M<'b>) -> M<'b>
Full name: Script.M`1.StaticBind
val mt : M<'a>
val fn : ('a -> M<'b>)
val result : M<'b>
M.Value: 'a
val newmessage : string
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val logmessages : string list
M.Value: 'b
val ret : x:'a -> M<'a>
Full name: Script.ret
 A shorter name for M.StaticReturn.
 Turning a variable of type 'a into M<'a> .
val x : 'a
val package : fn:('a -> 'b) -> mt:M<'a> -> M<'b>
Full name: Script.package
 Turning a function with signature 'a -> 'b  into  M<'a> -> M<'b> .
val fn : ('a -> 'b)
Multiple items
type ComputationExpressionBuilderType =
  new : unit -> ComputationExpressionBuilderType
  member Bind : mt:M<'a> * fn:('a -> M<'b>) -> M<'b>
  member Return : v:'c -> M<'c>
Full name: Script.ComputationExpressionBuilderType
 The builder type may be an empty class like this one.
 Often the builder instance is really nothing more than
 a syntactic requirement.
--------------------
new : unit -> ComputationExpressionBuilderType
val self : ComputationExpressionBuilderType
member ComputationExpressionBuilderType.Return : v:'c -> M<'c>
Full name: Script.ComputationExpressionBuilderType.Return
val v : 'c
member ComputationExpressionBuilderType.Bind : mt:M<'a> * fn:('a -> M<'b>) -> M<'b>
Full name: Script.ComputationExpressionBuilderType.Bind
type A = int
Full name: Script.A
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
type B = float
Full name: Script.B
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
type C = DateTime
Full name: Script.C
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end
Full name: System.DateTime
--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
type D = string
Full name: Script.D
type R = M<A>
Full name: Script.R
type S = M<B>
Full name: Script.S
type T = M<C>
Full name: Script.T
type U = M<D>
Full name: Script.U
val f : noWeeks:A -> B
Full name: Script.f
val noWeeks : A
val g : noDays:B -> C
Full name: Script.g
val noDays : B
val today : DateTime
Full name: Script.today
 Today's date and time for use in examples below.
DateTime.AddDays(value: float) : DateTime
val h : date:C -> D
Full name: Script.h
val date : C
DateTime.ToShortDateString() : string
val pf : (R -> S)
Full name: Script.pf
val pg : (S -> T)
Full name: Script.pg
val ph : (T -> U)
Full name: Script.ph
val fghOne : (R -> U)
Full name: Script.fghOne
val compose : fun1:('a -> 'b) * fun2:('b -> 'c) -> arg:'a -> 'c
Full name: Script.compose
 Our good old compose function from the first example
val fghTwo : (R -> U)
Full name: Script.fghTwo
val fghOneResult : U
Full name: Script.fghOneResult
val myInputParam : int
Full name: Script.myInputParam
 The test parameter I will use is "2" as in "two weeks from now".
val fghTwoResult : U
Full name: Script.fghTwoResult
val Mx : R
Full name: Script.Mx
val Mf : (A -> S)
Full name: Script.Mf
val Mg : (B -> T)
Full name: Script.Mg
val Mh : (C -> U)
Full name: Script.Mh
val builder : ComputationExpressionBuilderType
Full name: Script.builder
 By the construction of the syntax the builder must be an instance
 of the builder type. The static methods will not do by themselves.
val result : M<D>
Full name: Script.result
val a : A
val b : B
val c : C
val d : D
  
  
  More information