11[<AutoOpen>]
2- module Microsoft.VisualStudio.FSharp.Pervasive
2+ module Microsoft.VisualStudio.FSharp.Editor. Pervasive
33
44open System
5+ open System.Diagnostics
56
67[<RequireQualifiedAccess>]
78module String =
@@ -24,3 +25,196 @@ type System.IServiceProvider with
2425member x.GetService < 'T >() = x.GetService( typeof< 'T>) :?> 'T
2526member x.GetService < 'S , 'T >() = x.GetService( typeof< 'S>) :?> 'T
2627
28+ [<Sealed>]
29+ type MaybeBuilder () =
30+ // 'T -> M<'T>
31+ [<DebuggerStepThrough>]
32+ member inline __.Return value : 'T option =
33+ Some value
34+
35+ // M<'T> -> M<'T>
36+ [<DebuggerStepThrough>]
37+ member inline __.ReturnFrom value : 'T option =
38+ value
39+
40+ // unit -> M<'T>
41+ [<DebuggerStepThrough>]
42+ member inline __.Zero (): unit option =
43+ Some() // TODO: Should this be None?
44+
45+ // (unit -> M<'T>) -> M<'T>
46+ [<DebuggerStepThrough>]
47+ member __.Delay ( f : unit -> 'T option ): 'T option =
48+ f()
49+
50+ // M<'T> -> M<'T> -> M<'T>
51+ // or
52+ // M<unit> -> M<'T> -> M<'T>
53+ [<DebuggerStepThrough>]
54+ member inline __.Combine ( r1 , r2 : 'T option ): 'T option =
55+ match r1with
56+ | None->
57+ None
58+ | Some() ->
59+ r2
60+
61+ // M<'T> * ('T -> M<'U>) -> M<'U>
62+ [<DebuggerStepThrough>]
63+ member inline __.Bind ( value , f : 'T -> 'U option ): 'U option =
64+ Option.bind f value
65+
66+ // 'T * ('T -> M<'U>) -> M<'U> when 'U :> IDisposable
67+ [<DebuggerStepThrough>]
68+ member __.Using ( resource : ( 'T :> System.IDisposable ), body : _ -> _ option ): _ option =
69+ try body resource
70+ finally
71+ if not <| obj.ReferenceEquals( null , box resource) then
72+ resource.Dispose()
73+
74+ // (unit -> bool) * M<'T> -> M<'T>
75+ [<DebuggerStepThrough>]
76+ member x.While ( guard , body : _ option ): _ option =
77+ if guard() then
78+ // OPTIMIZE: This could be simplified so we don't need to make calls to Bind and While.
79+ x.Bind( body, ( fun () -> x.While( guard, body)))
80+ else
81+ x.Zero()
82+
83+ // seq<'T> * ('T -> M<'U>) -> M<'U>
84+ // or
85+ // seq<'T> * ('T -> M<'U>) -> seq<M<'U>>
86+ [<DebuggerStepThrough>]
87+ member x.For ( sequence : seq < _ >, body : 'T -> unit option ): _ option =
88+ // OPTIMIZE: This could be simplified so we don't need to make calls to Using, While, Delay.
89+ x.Using( sequence.GetEnumerator(), fun enum ->
90+ x.While(
91+ enum .MoveNext,
92+ x.Delay( fun () ->
93+ bodyenum .Current)))
94+
95+ let maybe = MaybeBuilder()
96+
97+ [<Sealed>]
98+ type AsyncMaybeBuilder () =
99+ [<DebuggerStepThrough>]
100+ member __.Return value : Async < 'T option > = Some value|> async.Return
101+
102+ [<DebuggerStepThrough>]
103+ member __.ReturnFrom value : Async < 'T option > = value
104+
105+ [<DebuggerStepThrough>]
106+ member __.ReturnFrom ( value : 'T option ) : Async < 'T option > = async.Return value
107+
108+ [<DebuggerStepThrough>]
109+ member __.Zero () : Async < unit option > =
110+ Some() |> async.Return
111+
112+ [<DebuggerStepThrough>]
113+ member __.Delay ( f : unit -> Async < 'T option >) : Async < 'T option > = f()
114+
115+ [<DebuggerStepThrough>]
116+ member __.Combine ( r1 , r2 : Async < 'T option >) : Async < 'T option > =
117+ async {
118+ let! r1 ' = r1
119+ match r1'with
120+ | None-> return None
121+ | Some() -> return ! r2
122+ }
123+
124+ [<DebuggerStepThrough>]
125+ member __.Bind ( value : Async < 'T option >, f : 'T -> Async < 'U option >) : Async < 'U option > =
126+ async {
127+ let! value ' = value
128+ match value'with
129+ | None-> return None
130+ | Some result-> return ! f result
131+ }
132+
133+ [<DebuggerStepThrough>]
134+ member __.Bind ( value : System.Threading.Tasks.Task < 'T >, f : 'T -> Async < 'U option >) : Async < 'U option > =
135+ async {
136+ let! value ' = Async.AwaitTask value
137+ return ! f value'
138+ }
139+
140+ [<DebuggerStepThrough>]
141+ member __.Bind ( value : 'T option , f : 'T -> Async < 'U option >) : Async < 'U option > =
142+ async {
143+ match valuewith
144+ | None-> return None
145+ | Some result-> return ! f result
146+ }
147+
148+ [<DebuggerStepThrough>]
149+ member __.Using ( resource : ( 'T :> IDisposable ), body : _ -> Async < _ option >) : Async < _ option > =
150+ try body resource
151+ finally if not ( isNull resource) then resource.Dispose()
152+
153+ [<DebuggerStepThrough>]
154+ member x.While ( guard , body : Async < _ option >) : Async < _ option > =
155+ if guard() then
156+ x.Bind( body, ( fun () -> x.While( guard, body)))
157+ else
158+ x.Zero()
159+
160+ [<DebuggerStepThrough>]
161+ member x.For ( sequence : seq < _ >, body : 'T -> Async < unit option >) : Async < _ option > =
162+ x.Using( sequence.GetEnumerator(), fun enum ->
163+ x.While( enum .MoveNext, x.Delay( fun () -> bodyenum .Current)))
164+
165+ [<DebuggerStepThrough>]
166+ member inline __.TryWith ( computation : Async < 'T option >, catchHandler : exn -> Async < 'T option >) : Async < 'T option > =
167+ async.TryWith( computation, catchHandler)
168+
169+ [<DebuggerStepThrough>]
170+ member inline __.TryFinally ( computation : Async < 'T option >, compensation : unit -> unit ) : Async < 'T option > =
171+ async.TryFinally( computation, compensation)
172+
173+ let asyncMaybe = AsyncMaybeBuilder()
174+
175+ let inline liftAsync ( computation : Async < 'T >) : Async < 'T option > =
176+ async {
177+ let! a = computation
178+ return Some a
179+ }
180+
181+ module Async =
182+ let map ( f : 'T -> 'U ) ( a : Async < 'T >) : Async < 'U > =
183+ async {
184+ let! a = a
185+ return f a
186+ }
187+
188+ let ignore ( a : Async < 'T >) : Async < unit > =
189+ async {
190+ let! _ = a
191+ return ()
192+ }
193+
194+ /// Creates an asynchronous workflow that runs the asynchronous workflow given as an argument at most once.
195+ /// When the returned workflow is started for the second time, it reuses the result of the previous execution.
196+ let cache ( input : Async < 'T >) =
197+ let agent = MailboxProcessor< AsyncReplyChannel<_>>. Start<| fun agent ->
198+ async {
199+ let! replyCh = agent.Receive()
200+ let! res = input
201+ replyCh.Reply res
202+ while true do
203+ let! replyCh = agent.Receive()
204+ replyCh.Reply res
205+ }
206+ async { return ! agent.PostAndAsyncReply id}
207+
208+ type AsyncBuilder with
209+ member __.Bind ( computation : System.Threading.Tasks.Task < 'a >, binder : 'a -> Async < 'b >): Async < 'b > =
210+ async {
211+ let! a = Async.AwaitTask computation
212+ return ! binder a
213+ }
214+
215+ member __.ReturnFrom ( computation : System.Threading.Tasks.Task < 'a >): Async < 'a > = Async.AwaitTask computation
216+
217+
218+ module Option =
219+ let guard ( x : bool ) : Option < unit > =
220+ if xthen Some() else None