42 people like it.

Disposable computation builder

Computation builder that provides easy way of constructing IDisposable objects. It supports elegant composition of disposable objects using 'do!' which can be used for example when working with 'IObservable' type.

Disposable builder declaration

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
type DisposableBuilder() =
  member x.Delay(f : unit -> IDisposable) = 
    { new IDisposable with 
        member x.Dispose() = f().Dispose() }
  member x.Bind(d1:IDisposable, f:unit -> IDisposable) = 
    let d2 = f()
    { new IDisposable with 
        member x.Dispose() = d1.Dispose(); d2.Dispose() }
  member x.Return(()) = x.Zero()
  member x.Zero() =
    { new IDisposable with 
        member x.Dispose() = () }

let disposable = DisposableBuilder()

Demo #1: Resetting console colors

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
// Creates disposable that resets console color when disposed
let resetColor() = 
  let clr = Console.ForegroundColor
  disposable { Console.ForegroundColor <- clr }

// Prints 'doing work' in red and resets color back
let demo1() =
  use unwind = resetColor()
  Console.ForegroundColor <- ConsoleColor.Red
  printfn "doing work"

demo1()        // Prints 'doing work' in red
printfn "done" // Prints 'done' in original color

Demo #2: Composing disposables

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
// Create two IDisposable objects that do some cleanup
let cleanup1 = disposable { 
  printfn "cleanup #1" }
let cleanup2 = disposable { 
  printfn "cleanup #1" }

let demo2() =
  // Dispose of both 'cleanup1' and 'cleanup2' when the
  // method finishes. This is useful for example when working
  // with IObservable (to dispose of event registrations)
  use d = disposable { 
    printfn "cleanup"
    do! cleanup1
    do! cleanup2 }
  printfn "foo"

demo2()
Multiple items
type DisposableBuilder =
  new : unit -> DisposableBuilder
  member Bind : d1:IDisposable * f:(unit -> IDisposable) -> IDisposable
  member Delay : f:(unit -> IDisposable) -> IDisposable
  member Return : unit -> IDisposable
  member Zero : unit -> IDisposable

Full name: Script.DisposableBuilder

--------------------
new : unit -> DisposableBuilder
val x : DisposableBuilder
member DisposableBuilder.Delay : f:(unit -> IDisposable) -> IDisposable

Full name: Script.DisposableBuilder.Delay
val f : (unit -> IDisposable)
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
type IDisposable =
  member Dispose : unit -> unit

Full name: System.IDisposable
val x : IDisposable
IDisposable.Dispose() : unit
member DisposableBuilder.Bind : d1:IDisposable * f:(unit -> IDisposable) -> IDisposable

Full name: Script.DisposableBuilder.Bind
val d1 : IDisposable
val d2 : IDisposable
member DisposableBuilder.Return : unit -> IDisposable

Full name: Script.DisposableBuilder.Return
member DisposableBuilder.Zero : unit -> IDisposable
member DisposableBuilder.Zero : unit -> IDisposable

Full name: Script.DisposableBuilder.Zero
val disposable : DisposableBuilder

Full name: Script.disposable
val resetColor : unit -> IDisposable

Full name: Script.resetColor
val clr : ConsoleColor
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...

Full name: System.Console
property Console.ForegroundColor: ConsoleColor
val demo1 : unit -> unit

Full name: Script.demo1
val unwind : IDisposable
type ConsoleColor =
  | Black = 0
  | DarkBlue = 1
  | DarkGreen = 2
  | DarkCyan = 3
  | DarkRed = 4
  | DarkMagenta = 5
  | DarkYellow = 6
  | Gray = 7
  | DarkGray = 8
  | Blue = 9
  ...

Full name: System.ConsoleColor
field ConsoleColor.Red = 12
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val cleanup1 : IDisposable

Full name: Script.cleanup1
val cleanup2 : IDisposable

Full name: Script.cleanup2
val demo2 : unit -> unit

Full name: Script.demo2
val d : IDisposable
Raw view Test code New version

More information

Link:http://fssnip.net/2s
Posted:13 years ago
Author:Tomas Petricek
Tags: disposable , computation builder , monad , rx , reactive