Skip to content

Commit db64dbc

Browse files
committed
Implement TaskSeq.indexed + tests & docs
1 parent dcda447 commit db64dbc

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

src/FSharpy.TaskSeq.Test/FSharpy.TaskSeq.Test.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<Compile Include="TaskSeq.Find.Tests.fs" />
2222
<Compile Include="TaskSeq.Fold.Tests.fs" />
2323
<Compile Include="TaskSeq.Head.Tests.fs" />
24+
<Compile Include="TaskSeq.Indexed.Tests.fs" />
2425
<Compile Include="TaskSeq.IsEmpty.fs" />
2526
<Compile Include="TaskSeq.Item.Tests.fs" />
2627
<Compile Include="TaskSeq.Iter.Tests.fs" />
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module FSharpy.Tests.Indexed
2+
3+
open Xunit
4+
open FsUnit.Xunit
5+
open FsToolkit.ErrorHandling
6+
7+
open FSharpy
8+
9+
//
10+
// TaskSeq.indexed
11+
//
12+
13+
module EmptySeq =
14+
[<Theory; ClassData(typeof<TestEmptyVariants>)>]
15+
let ``TaskSeq-indexed on empty`` variant =
16+
Gen.getEmptyVariant variant
17+
|> TaskSeq.indexed
18+
|> verifyEmpty
19+
20+
module Immutable =
21+
[<Fact>]
22+
let ``TaskSeq-indexed starts at zero`` () =
23+
taskSeq { yield 99 }
24+
|> TaskSeq.indexed
25+
|> TaskSeq.head
26+
|> Task.map (should equal (0, 99))
27+
28+
[<Theory; ClassData(typeof<TestImmTaskSeq>)>]
29+
let ``TaskSeq-indexed`` variant =
30+
Gen.getSeqImmutable variant
31+
|> TaskSeq.indexed
32+
|> TaskSeq.toArrayAsync
33+
|> Task.map (Array.forall (fun (x, y) -> x + 1 = y))
34+
|> Task.map (should be True)

src/FSharpy.TaskSeq/TaskSeq.fs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,10 @@ module TaskSeq =
165165

166166
let cast source : taskSeq<'T> = Internal.map (SimpleAction(fun (x: obj) -> x :?> 'T)) source
167167
let box source = Internal.map (SimpleAction(fun x -> box x)) source
168-
let unbox<'U when 'U: struct> (source: taskSeq<obj>) : taskSeq<'U> = Internal.map (SimpleAction(fun x -> unbox x)) source
168+
169+
let unbox<'U when 'U: struct> (source: taskSeq<obj>) : taskSeq<'U> =
170+
Internal.map (SimpleAction(fun x -> unbox x)) source
171+
169172
let iter action source = Internal.iter (SimpleAction action) source
170173
let iteri action source = Internal.iter (CountableAction action) source
171174
let iterAsync action source = Internal.iter (AsyncSimpleAction action) source
@@ -222,6 +225,14 @@ module TaskSeq =
222225
| None -> return invalidArg (nameof source) "The input sequence contains more than one element."
223226
}
224227

228+
let indexed (source: taskSeq<'T>) = taskSeq {
229+
let mutable i = 0
230+
231+
for x in source do
232+
yield i, x
233+
i <- i + 1
234+
}
235+
225236
let choose chooser source = Internal.choose (TryPick chooser) source
226237
let chooseAsync chooser source = Internal.choose (TryPickAsync chooser) source
227238
let filter predicate source = Internal.filter (Predicate predicate) source

src/FSharpy.TaskSeq/TaskSeq.fsi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ module TaskSeq =
125125
/// Maps over the taskSeq, applying the mapper function to each item. This function is non-blocking.
126126
val map: mapper: ('T -> 'U) -> source: taskSeq<'T> -> taskSeq<'U>
127127

128+
/// <summary>
129+
/// Builds a new task sequence whose elements are the corresponding elements of the input task
130+
/// sequence <paramref name="source" /> paired with the integer index (from 0) of each element.
131+
/// Does not evaluate the input sequence until requested.
132+
/// </summary>
133+
/// <param name="source">The input task sequence.</param>
134+
/// <returns>The resulting task sequence of tuples.</returns>
135+
/// <exception cref="T:ArgumentNullException">Thrown when the input sequence is null.</exception>
136+
val indexed: source: taskSeq<'T> -> taskSeq<int * 'T>
137+
128138
/// Maps over the taskSeq with an index, applying the mapper function to each item. This function is non-blocking.
129139
val mapi: mapper: (int -> 'T -> 'U) -> source: taskSeq<'T> -> taskSeq<'U>
130140

0 commit comments

Comments
 (0)