Skip to content

Instantly share code, notes, and snippets.

@games
Created November 17, 2017 12:16
Show Gist options
  • Select an option

  • Save games/3a8b95e8f262b265deff5e7821f0dba9 to your computer and use it in GitHub Desktop.

Select an option

Save games/3a8b95e8f262b265deff5e7821f0dba9 to your computer and use it in GitHub Desktop.
open System
open System.Diagnostics
[<Sealed>]
type MaybeBuilder () =
[<DebuggerStepThrough>]
member inline __.Return value: 'T option = Some value
[<DebuggerStepThrough>]
member inline __.ReturnFrom value: 'T option = value
[<DebuggerStepThrough>]
member inline __.Zero (): unit option = Some ()
[<DebuggerStepThrough>]
member __.Delay (f: unit -> 'T option): 'T option = f ()
[<DebuggerStepThrough>]
member inline __.Combine (r1, r2: 'T option): 'T option =
match r1 with
| None -> None
| Some () -> r2
[<DebuggerStepThrough>]
member inline __.Bind (value, f: 'T -> 'U option): 'U option = Option.bind f value
[<DebuggerStepThrough>]
member __.Using (resource: ('T :> System.IDisposable), body: _ -> _ option): _ option =
try body resource
finally if not <| obj.ReferenceEquals (null, box resource) then resource.Dispose ()
[<DebuggerStepThrough>]
member x.While (guard, body: _ option): _ option =
if guard () then
x.Bind (body, (fun () -> x.While (guard, body)))
else x.Zero ()
[<DebuggerStepThrough>]
member x.For (sequence: seq<_>, body: 'T -> unit option): _ option =
x.Using (sequence.GetEnumerator (), fun enum ->
x.While (enum.MoveNext,
x.Delay (fun () -> body enum.Current)
)
)
let maybe = MaybeBuilder()
let generate () =
let rng = new System.Random()
let v = rng.Next 10
if v % 2 = 0 then Some v else None
let compare x1 x2 =
match x1, x2 with
| Some v1, Some v2 -> Some (if v1 > v2 then v1 else v2)
| Some a, _ -> Some a
| _, Some b -> Some b
| _ -> None
let test1 () =
maybe {
let x1 = generate ()
let x2 = generate ()
return! compare x1 x2
}
let test2 () =
match generate () with
| Some _ as x1 ->
match generate () with
| Some _ as x2 -> compare x1 x2
| None -> None
| None -> None
let n = 1_000_000
printfn "------------ test1 -------------"
#time "on"
for _ in 1 .. n do
test1 () |> ignore
#time "off"
printfn "------------ test2 -------------"
#time "on"
for _ in 1 .. n do
test2 () |> ignore
#time "off"
@games
Copy link
Author

games commented Nov 17, 2017

test result:
------------ test1 -------------
Real: 00:00:02.323, CPU: 00:00:02.312, GC gen0: 129, gen1: 128, gen2: 1
------------ test2 -------------
Real: 00:00:01.537, CPU: 00:00:01.531, GC gen0: 84, gen1: 84, gen2: 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment