FSharp.Control.FusionTasks
FSharp.Control.FusionTasks copied to clipboard
Thank you for using FusionTasks, will archive in late 2022.
Thanks to the many users who have tried this library.
As you know, when F# was updated to 6.0, it supported a generic awaitable computation expression using SRTP. While we considered continuing to support it when the specification was not yet finalized, the new solution is generic enough that it no longer requires FusionTasks.
Originally, this library was implemented because F# uses Async and C# uses Task separately, which made it (somewhat) inconvenient to use the OSS libraries. This was a good experience that helped me to understand the concept of `asynchronous' in an abstract way, and thus the abstract concept of functional programming as a whole.
The FusionTasks NuGet package continues to be applicable and can probably be used in future versions of F#, as F# will probably maintain backward compatibility. It is one of my most cherished projects, and I am sad to see it end, but I will finish it properly.
I plan to archive it during 2022, around the end of the year.
Thank you for all again.
Features
-
Easy interoperable .NET Task/ValueTask <--> F#'s Async.
-
F# async workflow block now supports directly .NET Task/ValueTask handle with let!, do! and use!.
-
.NET (C# async-await) now supports directly F#'s Async.
-
SyncronizationContext capture operation support (F#: AsyncConfigure method / .NET (C#) AsAsyncConfigured method)
-
.NET now supports standard asynchronous sequence called IAsyncEnumerable<T>, FusionTasks supports it with for expression.
As far as I can see, NONE of the above feature list is covered by the new Task {} CE in F#. There is plenty of reason to carry on using async {} instead of task {} but async {} still doesn't easily consume Tasks or ValueTasks, C# still doesn't consume Asyncs and so on.
While it's true that you can use task {} it's not always a natural fit with existing API's or in general as a way to do asynchronous control flows compared with async {}, using MailboxProcessor for example which really require the use of Async, and async {} CEs can't consume Tasks directly. task {} CEs can consume Asyncs though.
(This is a complete ramble ;)
Thank you for showing us a summary of the benefits of FusionTasks. I'm very glad you did! These are precisely the motivations I felt were lacking in F#'s Async and designed FusionTasks to compensate for that. My own guess as to why these features have not been fully expanded in F#'s core library (just a guess, I don't know if such a discussion actually existed):
- With
Async.AwaitTask, it is easy to convert fromTasktoAsync. - If we don't use it and follow the FusionTasks method, you leave the type ambiguity to overload resolution, which is not F# culture. (I have noted this problem in the README.)
- On the surface,
AsyncandTasklook almost identical, butAsyncencapsulates a microscale computation, whileTaskserves as an object to connect the continuation of the computation. The very idea of connecting these seamlessly is not a good one.
... what I was thinking (in terms of maintenance).
On the other hand, I started with C# 1.0 as the language for .NET, and in order to use F# (both in the hobby and work domains), I could not ignore the overwhelming majority of libraries created by C#.
In F#, using libraries designed for F# is what boosts the F# programming experience the most, but to do so:
- Write code that P/Invoke directly from F# to create a library that connects to the real (native code) world.
- Write a wrapper library that calls the C# library from F#, with abstractions on the F# side that lean as much as possible on the F# type system. I believe that most of the F# libraries we see today take this approach.
Any of the above would involve a great deal of work. In particular, at the same time I felt this problem, C# 5.0 was in the process of introducing the async-await syntax with Task. Also, the average C# developer has a very difficult writing asynchronous processing (Task) safely, much less combining it with F#'s Async, and I had a very difficult giving lectures on it.
To avoid as much as possible incorrect writing of glue code with OSS libraries (for C#), and to reduce the barrier that C# developers have to overcome in order to touch F# and write code in F#, even if it is only in the scene of asynchronous processing. This would lead to an opportunity to get more people exposed to F#, which is why we created FusionTasks.
However, as a community activity, we have spent a great deal of time explaining asynchronous processing, from hardware to software, from the big picture to the smallest details, but I feel that even now it is difficult to say that such activities have come to fruition. In fact, I think that the syntactic rules of asynchronous processing have become so well accepted that it has become more difficult to understand the background.
To return to your point,
While it's true that you can use task {} it's not always a natural fit with existing API's or in general as a way to do asynchronous control flows compared With async {}, using MailboxProcessor for example which really requires the use of Async, and async {} CEs can't consume Tasks directly. task {} CEs can consume Asyncs though.
While it is certainly true:
- Perhaps a set of libraries written for F# will slowly overcome these, because compared to when FusionTasks was born, a growing number of libraries are being written for F#. If there is no library for F# and there is one for C#, we may end up having to write muddled code, but I think we are making progress.
- FusionTasks will be archived, but not removed. Because F# has a backward-compatible language processor (one of the things I like most about F# is that FSharp.Core is
netstandard2.0). So we can continue to FusionTasks. The current latest tfm isnet5.0, so maybe I will addnet6.0to reduce dependency before archived.
Finally deployed 2.6.0 package on nuget.org.
I put unit tests on F# 7.0 and exactly passed with no additional patching :) And minimized package dependency.
I really loved this project. Once again, thank you all!
あらためて、皆さん、ありがとうございました!