Skip to content

Commit bf49501

Browse files
committed
Use a delayed run for TaskBuilderTests
1 parent 0926e4f commit bf49501

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

tests/FSharpPlus.Tests/Helpers.fs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,56 @@ module SideEffects =
1414
let add x = effects.Add (x)
1515
let get () = effects |> Seq.toList
1616
let are lst = areEquivalent lst (get ())
17+
18+
module Rebuilders =
19+
// following code is copied from Builders.fs with a modified Run method
20+
open System
21+
open System.Collections.Generic
22+
open FSharpPlus
23+
open FSharpPlus.Control
24+
25+
type StrictBuilder<'``monad<'t>``> () =
26+
inherit FSharpPlus.GenericBuilders.Builder<'``monad<'t>``> ()
27+
member inline _.Delay ([<InlineIfLambda>]expr) = expr : unit -> '``Monad<'T>``
28+
member inline this.Run ([<InlineIfLambda>]expr: _->'``Monad<'T>``) = this.Bind (this.Return (), expr)
29+
member inline _.TryWith ([<InlineIfLambda>]expr, [<InlineIfLambda>]handler) = TryWith.InvokeForStrict expr handler : '``Monad<'T>``
30+
member inline _.TryFinally ([<InlineIfLambda>]expr, [<InlineIfLambda>]compensation) = TryFinally.InvokeForStrict expr compensation : '``Monad<'T>``
31+
32+
member inline _.Using (disposable: #IDisposable, [<InlineIfLambda>]body) = Using.Invoke disposable body
33+
34+
35+
36+
type MonadPlusStrictBuilder<'``monad<'t>``> () =
37+
inherit StrictBuilder<'``monad<'t>``> ()
38+
member _.YieldFrom expr = expr : '``monad<'t>``
39+
member inline _.Zero () = Empty.Invoke () : '``MonadPlus<'T>``
40+
member inline _.Combine (a: '``MonadPlus<'T>``, [<InlineIfLambda>]b) = a <|> b () : '``MonadPlus<'T>``
41+
member inline _.While ([<InlineIfLambda>]guard, [<InlineIfLambda>]body: unit -> '``MonadPlus<'T>``) : '``MonadPlus<'T>`` =
42+
let rec loop guard body =
43+
if guard () then body () <|> loop guard body
44+
else Empty.Invoke ()
45+
loop guard body
46+
member inline this.For (p: #seq<'T>, [<InlineIfLambda>]rest: 'T->'``MonadPlus<'U>``) =
47+
Using.Invoke (p.GetEnumerator () :> IDisposable) (fun enum ->
48+
let enum = enum :?> IEnumerator<_>
49+
this.While (enum.MoveNext, fun () -> rest enum.Current) : '``MonadPlus<'U>``)
50+
51+
type MonadFxStrictBuilder<'``monad<'t>``> () =
52+
inherit StrictBuilder<'``monad<'t>``> ()
53+
54+
member inline _.Zero () = result () : '``Monad<unit>``
55+
member inline _.Combine (a: '``Monad<unit>``, [<InlineIfLambda>]b) = a >>= fun () -> b () : '``Monad<'T>``
56+
57+
member inline _.While ([<InlineIfLambda>]guard, [<InlineIfLambda>]body: unit -> '``Monad<unit>``) : '``Monad<unit>`` =
58+
let rec loop guard body =
59+
if guard () then body () >>= fun () -> loop guard body
60+
else result ()
61+
loop guard body
62+
member inline this.For (p: #seq<'T>, [<InlineIfLambda>]rest: 'T->'``Monad<unit>``) =
63+
Using.Invoke (p.GetEnumerator () :> IDisposable) (fun enum ->
64+
let enum = enum :?> IEnumerator<_>
65+
this.While (enum.MoveNext, fun () -> rest enum.Current) : '``Monad<unit>``)
66+
67+
68+
/// Creates a strict monadic computation expression with a delayed Run method
69+
let drMonad<'``monad<'t>``> = new Rebuilders.MonadFxStrictBuilder<'``monad<'t>``> ()

tests/FSharpPlus.Tests/Task.fs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,12 @@ module Task =
282282
open System.Collections.Generic
283283
open System.Diagnostics
284284
open System.Threading
285-
open System.Threading.Tasks
285+
286+
// TaskBuilder uses a strict monad builder with delayed Run method
287+
// Therefore we need to use a lazy run to avoid eager execution
288+
// of the first instructions in the computation expression before
289+
// the first bind, which in some tests include a Thread.Sleep operation
290+
let monad'<'``monad<'t>``> = drMonad<'``monad<'t>``>
286291

287292
module Task =
288293
let Yield () =
@@ -965,7 +970,7 @@ module Task =
965970
testShortCircuitResult
966971
testDelay
967972
testNoDelay
968-
(fun () -> try testNonBlocking() with _ -> try testNonBlocking() with _ -> testNonBlocking())
973+
testNonBlocking
969974
testCatching1
970975
testCatching2
971976
testNestedCatching

tests/FSharpPlus.Tests/ValueTask.fs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,12 @@ module ValueTask =
235235
open System.Collections.Generic
236236
open System.Diagnostics
237237

238+
// TaskBuilder uses a strict monad builder with a delayed Run method
239+
// Therefore we need to use a lazy run to avoid eager execution
240+
// of the first instructions in the computation expression before
241+
// the first bind, which in some tests include a Thread.Sleep operation
242+
let monad'<'``monad<'t>``> = drMonad<'``monad<'t>``>
243+
238244
module ValueTask =
239245
let Yield () =
240246
let ya = Task.Yield().GetAwaiter ()
@@ -916,7 +922,7 @@ module ValueTask =
916922
testShortCircuitResult
917923
testDelay
918924
testNoDelay
919-
(fun () -> try testNonBlocking() with _ -> try testNonBlocking() with _ -> testNonBlocking())
925+
testNonBlocking
920926
testCatching1
921927
testCatching2
922928
testNestedCatching

0 commit comments

Comments
 (0)