diff --git a/README.md b/README.md
index a102b443..10c1b46f 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ The following is the progress report:
| | `compareWith` | `compareWith` | `compareWithAsync` | |
| ✅ [#69][] | `concat` | `concat` | | |
| ✅ [#70][] | `contains` | `contains` | | |
-| | `delay` | `delay` | | |
+| ✅ [#82][] | `delay` | `delay` | | |
| | `distinct` | `distinct` | | |
| | `distinctBy` | `dictinctBy` | `distinctByAsync` | |
| ✅ [#2][] | `empty` | `empty` | | |
@@ -610,4 +610,5 @@ module TaskSeq =
[#70]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/70
[#76]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/76
[#81]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/81
+[#82]: https://github.com/fsprojects/FSharp.Control.TaskSeq/pull/82
diff --git a/src/FSharp.Control.TaskSeq.Test/FSharp.Control.TaskSeq.Test.fsproj b/src/FSharp.Control.TaskSeq.Test/FSharp.Control.TaskSeq.Test.fsproj
index 4ab3edd3..d030c085 100644
--- a/src/FSharp.Control.TaskSeq.Test/FSharp.Control.TaskSeq.Test.fsproj
+++ b/src/FSharp.Control.TaskSeq.Test/FSharp.Control.TaskSeq.Test.fsproj
@@ -18,6 +18,7 @@
+
diff --git a/src/FSharp.Control.TaskSeq.Test/TaskSeq.Delay.Tests.fs b/src/FSharp.Control.TaskSeq.Test/TaskSeq.Delay.Tests.fs
new file mode 100644
index 00000000..20026528
--- /dev/null
+++ b/src/FSharp.Control.TaskSeq.Test/TaskSeq.Delay.Tests.fs
@@ -0,0 +1,54 @@
+module TaskSeq.Tests.Delay
+
+open System
+
+open Xunit
+open FsUnit.Xunit
+open FsToolkit.ErrorHandling
+
+open FSharp.Control
+open System.Collections.Generic
+
+//
+// TaskSeq.delay
+//
+
+let validateSequence ts =
+ ts
+ |> TaskSeq.toSeqCachedAsync
+ |> Task.map (Seq.map string)
+ |> Task.map (String.concat "")
+ |> Task.map (should equal "12345678910")
+
+module EmptySeq =
+ [)>]
+ let ``TaskSeq-delay with empty sequences`` variant =
+ fun () -> Gen.getEmptyVariant variant
+ |> TaskSeq.delay
+ |> verifyEmpty
+
+module Immutable =
+ [)>]
+ let ``TaskSeq-delay`` variant =
+ fun () -> Gen.getSeqImmutable variant
+ |> TaskSeq.delay
+ |> validateSequence
+
+module SideEffect =
+ []
+ let ``TaskSeq-delay executes side effects`` () = task {
+ let mutable i = 0
+
+ let ts =
+ fun () -> taskSeq {
+ yield! [ 1..10 ]
+ i <- i + 1
+ }
+ |> TaskSeq.delay
+
+ do! ts |> validateSequence
+ i |> should equal 1
+ let! len = TaskSeq.length ts
+ i |> should equal 2 // re-eval of the sequence executes side effect again
+ len |> should equal 10
+ }
diff --git a/src/FSharp.Control.TaskSeq/TaskSeq.fs b/src/FSharp.Control.TaskSeq/TaskSeq.fs
index a9ac3bd9..e26ea68c 100644
--- a/src/FSharp.Control.TaskSeq/TaskSeq.fs
+++ b/src/FSharp.Control.TaskSeq/TaskSeq.fs
@@ -164,6 +164,11 @@ module TaskSeq =
let initAsync count initializer = Internal.init (Some count) (InitActionAsync initializer)
let initInfiniteAsync initializer = Internal.init None (InitActionAsync initializer)
+ let delay (generator: unit -> taskSeq<'T>) =
+ { new IAsyncEnumerable<'T> with
+ member _.GetAsyncEnumerator(ct) = generator().GetAsyncEnumerator(ct)
+ }
+
let concat (sources: taskSeq<#taskSeq<'T>>) = taskSeq {
for ts in sources do
yield! (ts :> taskSeq<'T>)
diff --git a/src/FSharp.Control.TaskSeq/TaskSeq.fsi b/src/FSharp.Control.TaskSeq/TaskSeq.fsi
index 8787e63e..6c367526 100644
--- a/src/FSharp.Control.TaskSeq/TaskSeq.fsi
+++ b/src/FSharp.Control.TaskSeq/TaskSeq.fsi
@@ -39,6 +39,14 @@ module TaskSeq =
///
val lengthByAsync: predicate: ('T -> #Task) -> source: taskSeq<'T> -> Task
+ ///
+ /// Returns a task sequence that is given by the delayed specification of a task sequence.
+ ///
+ ///
+ /// The generating function for the task sequence.
+ /// The generated task sequence.
+ val delay: generator: (unit -> taskSeq<'T>) -> taskSeq<'T>
+
///
/// Generates a new task sequence which, when iterated, will return successive elements by calling the given function
/// with the current index, up to the given count. Each element is saved after its initialization for successive access to