Skip to content

Instantly share code, notes, and snippets.

@vasily-kirichenko
Created August 10, 2018 13:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vasily-kirichenko/2eb53efdbf37ed2a48598e6774218e37 to your computer and use it in GitHub Desktop.
Save vasily-kirichenko/2eb53efdbf37ed2a48598e6774218e37 to your computer and use it in GitHub Desktop.
[<AutoOpen>]
module CResult =
open System.Diagnostics
[<Sealed>]
type CResultBuilder () =
static let zero = Ok ()
member inline __.Return value : Result<'T, 'Error> = Ok value
[<CustomOperation("error")>]
member inline __.Error value : Result<'T, 'Error> = Error value
member inline __.ReturnFrom (value : Result<'T, 'InnerE>) : Result<'T, ^E> =
match value with
| Error e -> Error (^E: (static member From: 'InnerE -> ^E) (e))
| Ok x -> Ok x
[<DebuggerStepThrough>]
member __.Zero () : Result<unit, 'Error> = zero
[<DebuggerStepThrough>]
member __.Delay (generator : unit -> Result<'T, 'Error>) : Result<'T, 'Error> = generator ()
member inline __.Combine (r1, r2) : Result<'T, 'Error> =
match r1 with
| Error error -> Error error
| Ok () -> r2
member inline __.Bind (value: Result<'T, 'InnerE>, binder : 'T -> Result<'U, ^E>) : Result<'U, ^E> =
match value with
| Error e -> Error (^E: (static member From: 'InnerE -> ^E) (e))
| Ok x -> binder x
member inline __.TryWith (body : 'T -> Result<'U, 'Error>, handler) =
fun value -> try body value with ex -> handler ex
member inline __.TryFinally (body : 'T -> Result<'U, 'Error>, handler) =
fun value -> try body value finally handler ()
[<DebuggerStepThrough>]
member __.Using (resource : ('T :> System.IDisposable), body : _ -> Result<_,_>): Result<'U, 'Error> =
try body resource
finally if not (obj.ReferenceEquals (resource, null)) then resource.Dispose ()
let cresult = CResultBuilder()
module Parser =
type Error = Error
let parse _ = Result.Error Error
module IO =
type Error = Error
let save _ = Result.Error Error
[<NoComparison>]
type Error =
| Parser of Parser.Error
| IO of IO.Error
| Processing of exn
static member From (x: Error) = x
static member From (x: Parser.Error) = Parser x
static member From (x: IO.Error) = IO x
let doStuff : Result<unit, Error> =
cresult {
let! parsed = Parser.parse() // implicit convertion `Parser.Error` -> `Error`
let! saved = IO.save() // implicit convertion `IO.Error` -> `Error`
return! Error (Processing (exn "oops"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment