File tree Expand file tree Collapse file tree
tests/FSharpx.Async.Tests Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -7,6 +7,7 @@ namespace FSharpx.Control
77open System
88open System.Threading
99open System.IO
10+ open FSharpx.Control .Utils
1011
1112// ----------------------------------------------------------------------------
1213
@@ -474,6 +475,34 @@ module AsyncSeq =
474475 let inline zapp ( fs : AsyncSeq < 'a -> 'b >) ( s : AsyncSeq < 'a >) : AsyncSeq < 'b > =
475476 zipWith ((|>)) s fs
476477
478+ /// Traverses an async sequence an applies to specified function such that if None is returned the traversal short-circuits
479+ /// and None is returned as the result. Otherwise, the entire sequence is traversed and the result returned as Some.
480+ let rec traverseOptionAsync ( f : 'a -> Async < 'b option >) ( s : AsyncSeq < 'a >) : Async < AsyncSeq < 'b > option > = async {
481+ let! s = s
482+ match s with
483+ | Nil -> return Some ( Nil |> async.Return)
484+ | Cons( a, tl) ->
485+ let! b = f a
486+ match b with
487+ | Some b ->
488+ return ! traverseOptionAsync f tl |> Async.map ( Option.map ( fun tl -> Cons( b, tl) |> async.Return))
489+ | None ->
490+ return None }
491+
492+ /// Traverses an async sequence an applies to specified function such that if Choice2Of2 is returned the traversal short-circuits
493+ /// and Choice2Of2 is returned as the result. Otherwise, the entire sequence is traversed and the result returned as Choice1Of2.
494+ let rec traverseChoiceAsync ( f : 'a -> Async < Choice < 'b , 'e >>) ( s : AsyncSeq < 'a >) : Async < Choice < AsyncSeq < 'b >, 'e >> = async {
495+ let! s = s
496+ match s with
497+ | Nil -> return Choice1Of2 ( Nil |> async.Return)
498+ | Cons( a, tl) ->
499+ let! b = f a
500+ match b with
501+ | Choice1Of2 b ->
502+ return ! traverseChoiceAsync f tl |> Async.map ( Choice.mapl ( fun tl -> Cons( b, tl) |> async.Return))
503+ | Choice2Of2 e ->
504+ return Choice2Of2 e }
505+
477506 /// Returns an async computation which iterates the async sequence for
478507 /// its side-effects.
479508 let inline runAsync ( s : AsyncSeq < unit >) : Async < unit > =
Original file line number Diff line number Diff line change @@ -209,3 +209,31 @@ let ``AsyncSeq.replicate``() =
209209 let expected = List.replicate c x |> AsyncSeq.ofSeq
210210 Assert.True( EQ expected actual)
211211
212+ [<Test>]
213+ let ``AsyncSeq.traverseOptionAsync`` () =
214+ let seen = ResizeArray<_>()
215+ let s = [ 1 ; 2 ; 3 ; 4 ; 5 ] |> AsyncSeq.ofSeq
216+ let f i =
217+ seen.Add i
218+ if i < 2 then Some i |> async.Return
219+ else None |> async.Return
220+ let r = AsyncSeq.traverseOptionAsync f s |> Async.RunSynchronously
221+ match r with
222+ | Some _ -> Assert.Fail()
223+ | None -> Assert.True(([ 1 ; 2 ] = ( seen |> List.ofSeq)))
224+
225+ [<Test>]
226+ let ``AsyncSeq.traverseChoiceAsync`` () =
227+ let seen = ResizeArray<_>()
228+ let s = [ 1 ; 2 ; 3 ; 4 ; 5 ] |> AsyncSeq.ofSeq
229+ let f i =
230+ seen.Add i
231+ if i < 2 then Choice1Of2 i |> async.Return
232+ else Choice2Of2 " oh no" |> async.Return
233+ let r = AsyncSeq.traverseChoiceAsync f s |> Async.RunSynchronously
234+ match r with
235+ | Choice1Of2 _ -> Assert.Fail()
236+ | Choice2Of2 e ->
237+ Assert.AreEqual( " oh no" , e)
238+ Assert.True(([ 1 ; 2 ] = ( seen |> List.ofSeq)))
239+
You can’t perform that action at this time.
0 commit comments