FSharp.Control.TaskSeq
0.2.0
See the version list below for details.
dotnet add package FSharp.Control.TaskSeq --version 0.2.0
NuGet\Install-Package FSharp.Control.TaskSeq -Version 0.2.0
<PackageReference Include="FSharp.Control.TaskSeq" Version="0.2.0" />
<PackageVersion Include="FSharp.Control.TaskSeq" Version="0.2.0" />
<PackageReference Include="FSharp.Control.TaskSeq" />
paket add FSharp.Control.TaskSeq --version 0.2.0
#r "nuget: FSharp.Control.TaskSeq, 0.2.0"
#:package FSharp.Control.TaskSeq@0.2.0
#addin nuget:?package=FSharp.Control.TaskSeq&version=0.2.0
#tool nuget:?package=FSharp.Control.TaskSeq&version=0.2.0
TaskSeq
An implementation of IAsyncEnumerable<'T> as a taskSeq CE for F# with accompanying TaskSeq module.
The IAsyncEnumerable interface was added to .NET in .NET Core 3.0 and is part of .NET Standard 2.1. The main use-case was for iterative asynchronous enumeration over some resource. For instance, an event stream or a REST API interface with pagination, where each page is a MoveNextAsync call on the IAsyncEnumerator<'T> given by a call to GetAsyncEnumerator(). It has been relatively challenging to work properly with this type and dealing with each step being asynchronous, and the enumerator implementing IAsyncDisposable as well, which requires careful handling.
Table of contents
Implementation progress
As of 6 November 2022:
taskSeq CE
The resumable state machine backing the taskSeq CE is now finished and restartability (not to be confused with resumability) has been implemented and stabilized. Full support for empty task sequences is done. Focus is now on adding functionality there, like adding more useful overloads for yield and let!. Suggestions are welcome!
TaskSeq module functions
We are working hard on getting a full set of module functions on TaskSeq that can be used with IAsyncEnumerable sequences. Our guide is the set of F# Seq functions in F# Core and, where applicable, the functions provided from AsyncSeq. Each implemented function is documented through XML doc comments to provide the necessary context-sensitive help.
The following is the progress report:
| Done | Seq |
TaskSeq |
Variants | Remarks |
|---|---|---|---|---|
| ❓ | allPairs |
allPairs |
note #1 | |
| ✅ #81 | append |
append |
||
| ✅ #81 | appendSeq |
|||
| ✅ #81 | prependSeq |
|||
average |
average |
|||
averageBy |
averageBy |
averageByAsync |
||
| ❓ | cache |
cache |
note #1 | |
| ✅ #67 | cast |
cast |
||
| ✅ #67 | box |
|||
| ✅ #67 | unbox |
|||
| ✅ #23 | choose |
choose |
chooseAsync |
|
chunkBySize |
chunkBySize |
|||
| ✅ #11 | collect |
collect |
collectAsync |
|
| ✅ #11 | collectSeq |
collectSeqAsync |
||
compareWith |
compareWith |
compareWithAsync |
||
| ✅ #69 | concat |
concat |
||
| ✅ #70 | contains |
contains |
||
| ✅ #82 | delay |
delay |
||
distinct |
distinct |
|||
distinctBy |
dictinctBy |
distinctByAsync |
||
| ✅ #2 | empty |
empty |
||
| ✅ #23 | exactlyOne |
exactlyOne |
||
except |
except |
|||
| ✅ #70 | exists |
exists |
existsAsync |
|
exists2 |
exists2 |
|||
| ✅ #23 | filter |
filter |
filterAsync |
|
| ✅ #23 | find |
find |
findAsync |
|
| 🚫 | findBack |
note #2 | ||
| ✅ #68 | findIndex |
findIndex |
findIndexAsync |
|
| 🚫 | findIndexBack |
n/a | n/a | note #2 |
| ✅ #2 | fold |
fold |
foldAsync |
|
fold2 |
fold2 |
fold2Async |
||
| 🚫 | foldBack |
note #2 | ||
| 🚫 | foldBack2 |
note #2 | ||
forall |
forall |
forallAsync |
||
forall2 |
forall2 |
forall2Async |
||
| ❓ | groupBy |
groupBy |
groupByAsync |
note #1 |
| ✅ #23 | head |
head |
||
| ✅ #68 | indexed |
indexed |
||
| ✅ #69 | init |
init |
initAsync |
|
| ✅ #69 | initInfinite |
initInfinite |
initInfiniteAsync |
|
insertAt |
insertAt |
|||
insertManyAt |
insertManyAt |
|||
| ✅ #23 | isEmpty |
isEmpty |
||
| ✅ #23 | item |
item |
||
| ✅ #2 | iter |
iter |
iterAsync |
|
iter2 |
iter2 |
iter2Async |
||
| ✅ #2 | iteri |
iteri |
iteriAsync |
|
iteri2 |
iteri2 |
iteri2Async |
||
| ✅ #23 | last |
last |
||
| ✅ #53 | length |
length |
||
| ✅ #53 | lengthBy |
lengthByAsync |
||
| ✅ #2 | map |
map |
mapAsync |
|
map2 |
map2 |
map2Async |
||
map3 |
map3 |
map3Async |
||
mapFold |
mapFold |
mapFoldAsync |
||
| 🚫 | mapFoldBack |
note #2 | ||
| ✅ #2 | mapi |
mapi |
mapiAsync |
|
mapi2 |
mapi2 |
mapi2Async |
||
max |
max |
|||
maxBy |
maxBy |
maxByAsync |
||
min |
min |
|||
minBy |
minBy |
minByAsync |
||
| ✅ #2 | ofArray |
ofArray |
||
| ✅ #2 | ofAsyncArray |
|||
| ✅ #2 | ofAsyncList |
|||
| ✅ #2 | ofAsyncSeq |
|||
| ✅ #2 | ofList |
ofList |
||
| ✅ #2 | ofTaskList |
|||
| ✅ #2 | ofResizeArray |
|||
| ✅ #2 | ofSeq |
|||
| ✅ #2 | ofTaskArray |
|||
| ✅ #2 | ofTaskList |
|||
| ✅ #2 | ofTaskSeq |
|||
pairwise |
pairwise |
|||
permute |
permute |
permuteAsync |
||
| ✅ #23 | pick |
pick |
pickAsync |
|
| 🚫 | readOnly |
note #3 | ||
reduce |
reduce |
reduceAsync |
||
| 🚫 | reduceBack |
note #2 | ||
removeAt |
removeAt |
|||
removeManyAt |
removeManyAt |
|||
replicate |
replicate |
|||
| ❓ | rev |
note #1 | ||
scan |
scan |
scanAsync |
||
| 🚫 | scanBack |
note #2 | ||
singleton |
singleton |
|||
skip |
skip |
|||
skipWhile |
skipWhile |
skipWhileAsync |
||
| ❓ | sort |
note #1 | ||
| ❓ | sortBy |
note #1 | ||
| ❓ | sortByAscending |
note #1 | ||
| ❓ | sortByDescending |
note #1 | ||
| ❓ | sortWith |
note #1 | ||
splitInto |
splitInto |
|||
sum |
sum |
|||
sumBy |
sumBy |
sumByAsync |
||
| ✅ #76 | tail |
tail |
||
take |
take |
|||
takeWhile |
takeWhile |
takeWhileAsync |
||
| ✅ #2 | toArray |
toArray |
toArrayAsync |
|
| ✅ #2 | toIList |
toIListAsync |
||
| ✅ #2 | toList |
toList |
toListAsync |
|
| ✅ #2 | toResizeArray |
toResizeArrayAsync |
||
| ✅ #2 | toSeq |
toSeqAsync |
||
| […] | ||||
| ❓ | transpose |
note #1 | ||
truncate |
truncate |
|||
| ✅ #23 | tryExactlyOne |
tryExactlyOne |
tryExactlyOneAsync |
|
| ✅ #23 | tryFind |
tryFind |
tryFindAsync |
|
| 🚫 | tryFindBack |
note #2 | ||
| ✅ #68 | tryFindIndex |
tryFindIndex |
tryFindIndexAsync |
|
| 🚫 | tryFindIndexBack |
note #2 | ||
| ✅ #23 | tryHead |
tryHead |
||
| ✅ #23 | tryItem |
tryItem |
||
| ✅ #23 | tryLast |
tryLast |
||
| ✅ #23 | tryPick |
tryPick |
tryPickAsync |
|
| ✅ #76 | tryTail |
|||
unfold |
unfold |
unfoldAsync |
||
updateAt |
updateAt |
|||
where |
where |
whereAsync |
||
windowed |
windowed |
|||
| ✅ #2 | zip |
zip |
||
zip3 |
zip3 |
|||
zip4 |
<sup>¹⁾ <a id="note1"></a>These functions require a form of pre-materializing through TaskSeq.cache, similar to the approach taken in the corresponding Seq functions. It doesn't make much sense to have a cached async sequence. However, AsyncSeq does implement these, so we'll probably do so eventually as well.</sup>
<sup>²⁾ <a id="note2"></a>Because of the async nature of TaskSeq sequences, iterating from the back would be bad practice. Instead, materialize the sequence to a list or array and then apply the xxxBack iterators.</sup>
<sup>³⁾ <a id="note3"></a>The motivation for readOnly in Seq is that a cast from a mutable array or list to a seq<_> is valid and can be cast back, leading to a mutable sequence. Since TaskSeq doesn't implement IEnumerable<_>, such casts are not possible.</sup>
More information
Futher reading IAsyncEnumerable
- A good C#-based introduction can be found in this blog.
- An MSDN article written shortly after it was introduced.
- Converting a
seqto anIAsyncEnumerabledemo gist as an example, thoughTaskSeqcontains many more utility functions and uses a slightly different approach. - If you're looking for using
IAsyncEnumerablewithasyncand nottask, the excellentAsyncSeqlibrary should be used. WhileTaskSeqis intended to consumeasyncjust liketaskdoes, it won't create anAsyncSeqtype (at least not yet). If you want classic Async and parallelism, you should get this library instead.
Futher reading on resumable state machines
- A state machine from a monadic perspective in F# can be found here, which works with the pre-F# 6.0 non-resumable internals.
- The original RFC for F# 6.0 on resumable state machines
- The original RFC for introducing
taskto F# 6.0. - A pre F# 6.0
TaskBuilderthat motivated thetaskCE later added to F# Core. - MSDN Documentation on
taskandasync.
Further reading on computation expressions
- Docs on MSDN form a good summary and starting point.
- Arguably the best step-by-step tutorial to using and building computation expressions by Scott Wlaschin.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- FSharp.Core (>= 6.0.2)
NuGet packages (20)
Showing the top 5 NuGet packages that depend on FSharp.Control.TaskSeq:
| Package | Downloads |
|---|---|
|
Propulsion
Efficient event streaming pipelines |
|
|
Equinox.CosmosStore
Efficient event sourced decisions and data |
|
|
Equinox.EventStore
Efficient event sourced decisions and data |
|
|
Propulsion.Feed
Efficient event streaming pipelines |
|
|
Equinox.DynamoStore
Efficient event sourced decisions and data |
GitHub repositories (2)
Showing the top 2 popular GitHub repositories that depend on FSharp.Control.TaskSeq:
| Repository | Stars |
|---|---|
|
StockSharp/StockSharp
Algorithmic trading and quantitative trading open source platform to develop trading robots (stock markets, forex, crypto, bitcoins, and options).
|
|
|
nozzlegear/ShopifySharp
ShopifySharp is a .NET library that helps developers easily authenticate with and manage Shopify stores using Shopify's GraphQL API.
|
v.0.2
- moved from NET 6.0, to NetStandard 2.1 for greater compatibility, no functional changes
- move to minimally necessary FSharp.Core version: 6.0.2
- updated readme with progress overview, corrected meta info, added release notes
v.0.1.1
- updated meta info in nuget package and added readme
v.0.1
- initial release