The example in the article you mentioned really looks just like let!
from asynchronous workflows. In general, the yield return
keyword in C# makes it possible to encode patterns similar to F# computation expressions (in a weird way, because it was designed for creating enumerators):
- This is also used by AsyncEnumerator, which is (IMHO) simpler than CCR and a bit closer to F# asynchronous workflows
- I wrote an article that explains this similartiy in more details.
I think that the key difference between CCR and F# asynchronous workflows is that CCR also includes libraries for message-passing concurrency. See for example this article - it uses Port
class (you can send messages to ports) and Arbiter.Receive
, which is a primitive that allows you to wait for messages from Port
.
In F#, you can use MailboxProcessor
for implementing the same message-passing communication pattern, but this isn't a built-in part of F# asynchronous workflows - MailboxProcessor
is implemented using asynchronous workflows.
In summary: I think that F# asynchronous workflows are simpler and conceptually clearer. However, CCR and asynchronous workflows together with MailboxProcessor
implement roughly the same programming pattern.