3 people like it.
    Like the snippet!
  
  Simple builder example: Nullable
  Simple Computational expressions / monad / builder -example, using .NET Nullable as demo.
  |  1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
75: 
76: 
77: 
78: 
79: 
80: 
 | module BuilderExample
open System
//------------------------------------------------
//Example 1: First try, just return
type Nullable1Builder() =
    member this.Return(x) = Nullable(x)
let myNullable1 = Nullable1Builder()
let MakeNullable =
    myNullable1{
        let a = 5 + 1
        return a // calls builders Return(x)
    }
//val test : Nullable<int> = 6
//------------------------------------------------
//Example 2: nullable { ... } with combining functionality
type Nullable2Builder() =
    let hasValue (a:Nullable<'a>) = a.HasValue 
    member t.Return(x) = Nullable(x)
    member t.Bind(x, rest) = 
        match hasValue x with 
        | false -> System.Nullable() 
        | true -> rest(x.Value)
let nullable = Nullable2Builder()
let test =
    nullable{
        let! a = System.Nullable(3) // Call Bind
        let! b = System.Nullable(5) // Call Bind
        //Inside computation expression(/monad): easy programming without Nullable-worries:
        let mult = a * b 
        let sum = mult + 1 
        return sum //Call Return
    }
//val test : Nullable<int> = 16
//------------------------------------------------------------------------------
// using e.g.
//     let! b = System.Nullable() 
// would cause to return:
//     val test : System.Nullable()
// own { ...} syntax is made with implementing Builder-class
// and (some of) the "interface" members
//------------------------------------------------------------------------------
// Some optional technical details:
// Actual stack in example2, you don't have to care about this:
// nullable.Bind(Nullable(3), (fun res1 ->
//   nullable.Bind(Nullable(5), (fun res2 ->
//     nullable.Let(res1*res2, (fun res3 ->
//       nullable.Let(res3+1, (fun res4 ->
//         nullable.Return(res4)))))))))
//------------------------------------------------
// Further reading:
// Interface described in: http://msdn.microsoft.com/en-us/library/dd233182.aspx
// More info: http://blogs.msdn.com/b/dsyme/archive/2007/09/22/some-details-on-f-computation-expressions-aka-monadic-or-workflow-syntax.aspx
// Check also Reactive Extensions 2.0 with F# observe { ... }:
// https://github.com/panesofglass/FSharp.Reactive/blob/master/src/Observable.fs
// and: http://fssnip.net/tags/computation+builder and http://fssnip.net/tags/monad
 | 
module BuilderExample
namespace System
Multiple items
type Nullable1Builder =
  new : unit -> Nullable1Builder
  member Return : x:'a -> Nullable<'a> (requires default constructor and value type and 'a :> ValueType)
Full name: BuilderExample.Nullable1Builder
--------------------
new : unit -> Nullable1Builder
val this : Nullable1Builder
member Nullable1Builder.Return : x:'a -> Nullable<'a> (requires default constructor and value type and 'a :> ValueType)
Full name: BuilderExample.Nullable1Builder.Return
val x : 'a (requires default constructor and value type and 'a :> ValueType)
Multiple items
type Nullable =
  static member Compare<'T> : n1:Nullable<'T> * n2:Nullable<'T> -> int
  static member Equals<'T> : n1:Nullable<'T> * n2:Nullable<'T> -> bool
  static member GetUnderlyingType : nullableType:Type -> Type
Full name: System.Nullable
--------------------
type Nullable<'T (requires default constructor and value type and 'T :> ValueType)> =
  struct
    new : value:'T -> Nullable<'T>
    member Equals : other:obj -> bool
    member GetHashCode : unit -> int
    member GetValueOrDefault : unit -> 'T + 1 overload
    member HasValue : bool
    member ToString : unit -> string
    member Value : 'T
  end
Full name: System.Nullable<_>
--------------------
Nullable()
Nullable(value: 'T) : unit
val myNullable1 : Nullable1Builder
Full name: BuilderExample.myNullable1
val MakeNullable : Nullable<int>
Full name: BuilderExample.MakeNullable
val a : int
Multiple items
type Nullable2Builder =
  new : unit -> Nullable2Builder
  member Bind : x:Nullable<'a> * rest:('a -> Nullable<'b>) -> Nullable<'b> (requires default constructor and value type and 'a :> ValueType and default constructor and value type and 'b :> ValueType)
  member Return : x:'c -> Nullable<'c> (requires default constructor and value type and 'c :> ValueType)
Full name: BuilderExample.Nullable2Builder
--------------------
new : unit -> Nullable2Builder
val hasValue : (Nullable<'a> -> bool) (requires default constructor and value type and 'a :> ValueType)
val a : Nullable<'a> (requires default constructor and value type and 'a :> ValueType)
property Nullable.HasValue: bool
val t : Nullable2Builder
member Nullable2Builder.Return : x:'c -> Nullable<'c> (requires default constructor and value type and 'c :> ValueType)
Full name: BuilderExample.Nullable2Builder.Return
val x : 'c (requires default constructor and value type and 'c :> ValueType)
member Nullable2Builder.Bind : x:Nullable<'a> * rest:('a -> Nullable<'b>) -> Nullable<'b> (requires default constructor and value type and 'a :> ValueType and default constructor and value type and 'b :> ValueType)
Full name: BuilderExample.Nullable2Builder.Bind
val x : Nullable<'a> (requires default constructor and value type and 'a :> ValueType)
val rest : ('a -> Nullable<'b>) (requires default constructor and value type and 'a :> ValueType and default constructor and value type and 'b :> ValueType)
property Nullable.Value: 'a
val nullable : Nullable2Builder
Full name: BuilderExample.nullable
val test : Nullable<int>
Full name: BuilderExample.test
val b : int
val mult : int
val sum : int
  
  
  More information