Skip to content

Instantly share code, notes, and snippets.

@michael-newton-15below
Created January 16, 2013 20:00
Show Gist options
  • Save michael-newton-15below/4550342 to your computer and use it in GitHub Desktop.
Save michael-newton-15below/4550342 to your computer and use it in GitHub Desktop.
Decomposing error handling computational expression without use
// Our builder
type TestErrorBuilder () =
member this.Bind (expr, func) =
match expr with
| None -> None
| Some r ->
try func r
with
| _ as e ->
printfn "%A" e
None
member this.Delay (f: unit -> _) =
f ()
member this.Return (value) =
Some value
member this.ReturnFrom (value) =
value
member this.TryFinally (expr, comp) =
try this.ReturnFrom(expr)
finally comp ()
member this.Using (res : #System.IDisposable, expr) =
this.TryFinally(expr res, fun () -> res.Dispose())
interface IErrorHandlerBuilder with
member this.Bind (expr, func) = this.Bind (expr, func)
member this.Delay (f) = this.Delay (f)
member this.Return (value) = this.Return (value)
member this.ReturnFrom (value) = this.ReturnFrom(value)
member this.TryFinally (expr, comp) = this.TryFinally (expr, comp)
member this.Using (res : #System.IDisposable, expr) = this.Using (res, expr)
member this.Zero () = None
let audit = TestErrorBuilder ()
// Our basic cexpr, fully sugared
let calculate input =
audit {
let! thing = Some input
return (possibleGoWrongThing thing)
}
// Rest of this might not be valid f# code at every step.
// Expanding using documentation at http://msdn.microsoft.com/en-us/library/dd233182.aspx
// Step one: Delay
let calculate input =
audit.Delay(fun () ->
audit {
let! thing = Some input
return (possibleGoWrongThing thing)
})
// Step two: First bind
let calculate input =
audit.Delay(fun () ->
audit.Bind(Some input, fun thing ->
audit {
return (possibleGoWrongThing thing)
}))
// Step three: Return
let calculate input =
audit.Delay(fun () ->
audit.Bind(Some input, fun thing ->
audit.Return (possibleGoWrongThing thing)))
// Step four: Expand Bind
let calculate input =
audit.Delay(fun () ->
match Some input with
| None -> None
| Some thing ->
try
fun thing ->
audit.Return (possibleGoWrongThing thing)
with
| _ as e ->
printfn "%A" e
None)
// Step five: Expand Return
let calculate input =
audit.Delay(fun () ->
match Some input with
| None -> None
| Some thing ->
try
fun thing ->
Some (possibleGoWrongThing thing)
with
| _ as e ->
printfn "%A" e
None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment