@@ -66,6 +66,84 @@ module Immutable =
6666 String letters2 |> should equal " ABCDE"
6767 }
6868
69+ module Immutable2 =
70+ [<Theory; ClassData( typeof< TestImmTaskSeq>) >]
71+ let ``TaskSeq - choose returns all when chooser always returns Some`` variant = task {
72+ let ts = Gen.getSeqImmutable variant
73+ let! xs = ts |> TaskSeq.choose Some |> TaskSeq.toArrayAsync
74+ xs |> should equal [| 1 .. 10 |]
75+ }
76+
77+ [<Theory; ClassData( typeof< TestImmTaskSeq>) >]
78+ let ``TaskSeq - chooseAsync returns all when chooser always returns Some`` variant = task {
79+ let ts = Gen.getSeqImmutable variant
80+
81+ let! xs =
82+ ts
83+ |> TaskSeq.chooseAsync ( fun x -> task { return Some x })
84+ |> TaskSeq.toArrayAsync
85+
86+ xs |> should equal [| 1 .. 10 |]
87+ }
88+
89+ [<Theory; ClassData( typeof< TestImmTaskSeq>) >]
90+ let ``TaskSeq - choose returns empty when chooser always returns None`` variant = task {
91+ let ts = Gen.getSeqImmutable variant
92+
93+ do ! ts |> TaskSeq.choose ( fun _ -> None) |> verifyEmpty
94+ }
95+
96+ [<Theory; ClassData( typeof< TestImmTaskSeq>) >]
97+ let ``TaskSeq - chooseAsync returns empty when chooser always returns None`` variant = task {
98+ let ts = Gen.getSeqImmutable variant
99+
100+ do !
101+ ts
102+ |> TaskSeq.chooseAsync ( fun _ -> task { return None })
103+ |> verifyEmpty
104+ }
105+
106+ [<Fact>]
107+ let ``TaskSeq - choose with singleton sequence and Some chooser returns singleton`` () = task {
108+ let! xs =
109+ taskSeq { yield 42 }
110+ |> TaskSeq.choose ( fun x -> Some( x * 2 ))
111+ |> TaskSeq.toListAsync
112+
113+ xs |> should equal [ 84 ]
114+ }
115+
116+ [<Fact>]
117+ let ``TaskSeq - choose with singleton sequence and None chooser returns empty`` () =
118+ taskSeq { yield 42 }
119+ |> TaskSeq.choose ( fun _ -> None)
120+ |> verifyEmpty
121+
122+ [<Fact>]
123+ let ``TaskSeq - choose can change the element type`` () = task {
124+ // choose maps int -> string option, verifying type-changing behavior
125+ let chooser n = if n % 2 = 0 then Some( sprintf " even-%d " n) else None
126+
127+ let! xs =
128+ taskSeq { yield ! [ 1 .. 6 ] }
129+ |> TaskSeq.choose chooser
130+ |> TaskSeq.toListAsync
131+
132+ xs |> should equal [ " even-2" ; " even-4" ; " even-6" ]
133+ }
134+
135+ [<Fact>]
136+ let ``TaskSeq - chooseAsync can change the element type`` () = task {
137+ let chooser n = task { return if n % 2 = 0 then Some( sprintf " even-%d " n) else None }
138+
139+ let! xs =
140+ taskSeq { yield ! [ 1 .. 6 ] }
141+ |> TaskSeq.chooseAsync chooser
142+ |> TaskSeq.toListAsync
143+
144+ xs |> should equal [ " even-2" ; " even-4" ; " even-6" ]
145+ }
146+
69147module SideEffects =
70148 [<Theory; ClassData( typeof< TestSideEffectTaskSeq>) >]
71149 let ``TaskSeq - choose applied multiple times`` variant = task {
@@ -94,3 +172,41 @@ module SideEffects =
94172 String lettersK |> should equal " KLMNO"
95173 String lettersU |> should equal " UVWXY"
96174 }
175+
176+ [<Fact>]
177+ let ``TaskSeq - choose evaluates each source element exactly once`` () = task {
178+ let mutable count = 0
179+
180+ let ts = taskSeq {
181+ for i in 1 .. 5 do
182+ count <- count + 1
183+ yield i
184+ }
185+
186+ let! xs =
187+ ts
188+ |> TaskSeq.choose ( fun x -> if x < 3 then Some x else None)
189+ |> TaskSeq.toListAsync
190+
191+ count |> should equal 5 // all 5 elements were visited
192+ xs |> should equal [ 1 ; 2 ]
193+ }
194+
195+ [<Fact>]
196+ let ``TaskSeq - chooseAsync evaluates each source element exactly once`` () = task {
197+ let mutable count = 0
198+
199+ let ts = taskSeq {
200+ for i in 1 .. 5 do
201+ count <- count + 1
202+ yield i
203+ }
204+
205+ let! xs =
206+ ts
207+ |> TaskSeq.chooseAsync ( fun x -> task { return if x < 3 then Some x else None })
208+ |> TaskSeq.toListAsync
209+
210+ count |> should equal 5
211+ xs |> should equal [ 1 ; 2 ]
212+ }
0 commit comments