@@ -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> `` > ()
0 commit comments