TryJoinads (IV.) - Concurrency using join calculus
Join calculus provides a declarative way of expressing asynchronous synchronization
patterns. It has been use as a basis for programming languages (JoCaml and COmega), but also
as a basis for libraries (embedded in C# and Scala). Using joinads, it is possible to
embed join calculus in F# with a nice syntax using the match!
construct. Formally,
join calculus does not form a monad, but it can be viewed as a version of joinad
as described in the first paper on joinads.
The programming model is based on channels and join patterns. A channel can be viewed as a thread-safe mailbox into which we can put values without blocking the caller. In some sense, this is quite similar to F# agents. A join pattern is then a rule saying that a certain combination of values in channels should trigger a specific reaction (and remove values from the channels). The ability to match on multiple channels distinguishes join calculus from F# agents.
Note: This blog post is a re-publication of a tutorial from the TryJoinads.org web page. If you read the article there, you can run the examples interactively and experiment with them: view the article on TryJoinads.
Published: Wednesday, 22 February 2012, 5:38 PM
Tags:
f#, research, joinads, asynchronous, parallel
Read the complete article
TryJoinads (III.): Agent-based programming
Another area where the match!
syntax can be used is when programming with F# agents,
implemented by the MailboxProcessor
type. Formally, agents do not form the monad
structure in a useful way - when programming with agents, we do not compose a new agents,
but instead we write code that (imperatively) receives messages from the agent's mailbox
and handles them.
This article demonstrates an agent { ... }
computation builder that can be used for
implementing the body of an agent. Normally, the body of an agent is an asynchronous
workflow. The code in the body uses let!
to perform asynchronous operations, most
importantly to call inbox.Receive
to get the next message from the inbox. When the
agent intends to handle only certain kinds of messages, it can use inbox.Scan
. When
using the agent
builder, pattern matching on messages can be written using match!
and
it is possible to write code that ignores certain types of messages simply by writing an
incomplete pattern matching.
Note: This blog post is a re-publication of a tutorial from the TryJoinads.org web page. If you read the article there, you can run the examples interactively and experiment with them: view the article on TryJoinads.
Published: Monday, 20 February 2012, 12:36 PM
Tags:
joinads, research, f#, parallel, asynchronous
Read the complete article
TryJoinads (II.): Task-based parallelism
The implementation of joinad operations for the Task<'T>
type is quite similar to the
implementation of Async<'T>
, because the two types have similar properties. They both
produce at most one value (or an exception) and they both take some time to complete.
Just like for asynchronous workflows, pattern matching on multiple computations using
match!
gives us a parallel composition (with the two tasks running in parallel) and
choice between clauses is non-deterministic, depending on which clause completes first.
Unlike asynchronous workflows, the Task<'T>
type does not require any support for
aliasing. A value of type Task<'T>
represents a running computation that can be
accessed from multiple parts of program. In this sense, the type Async<'T>
is more
similar to a function unit -> Task<'T>
than to the type Task<'T>
itself.
The key difference between tasks and asynchronous workflows is that the latter provides better support for writing non-blocking computations that involve asynchronous long-running operations such as I/O or waiting for a certain event. Tasks are more suitable for high-performance CPU-intensive computations.
Note: This blog post is a re-publication of a tutorial from the TryJoinads.org web page. If you read the article there, you can run the examples interactively and experiment with them: view the article on TryJoinads.
Published: Friday, 17 February 2012, 1:10 PM
Tags:
research, f#, parallel, joinads
Read the complete article
TryJoinads (I.) - Asynchronous programming
Asynchronous workflows provide a way of writing code that does not block a thread
when waiting for a completion of long-running operation such as web service call,
another I/O operation or waiting for the completion of some background operation.
In this article, we look at the new expressive power that joinads add to
asynchronous workflows written using the async { ... }
block in F#.
Note: This blog post is a re-publication of a tutorial from the TryJoinads.org web page. If you read the article there, you can run the examples interactively and experiment with them: view the article on TryJoinads.
Published: Monday, 13 February 2012, 5:35 PM
Tags:
f#, research, joinads
Read the complete article
Introducing TryJoinads.org
If you have been following my blog, you've probably already heard of joinads. It is a research extension of F# computation expressions (or monads in Haskell). The extension makes computation expressions more useful in domains like parallel, concurrent and reactive programming. However, it can be used for any type of computation including, for example, parsers. If you're interested in detailed description, you can find it in two academic papers that I blogged about previously: PADL 2011 and Haskell 2011.
The extension adds a keyword match!
- as the syntax suggests, it is akin to pattern
matching using match
, but instead of pattern matching on values, you can pattern match
on computations like Async<'T>
(or on other monadic values). Just like other features of
computation expressions, the match!
syntax is translated to applications of several
methods defined by the computation builder.
I won't say more about joinads in this post, because you can now easily try joinads yourself...
Published: Monday, 13 February 2012, 4:21 PM
Tags:
parallel, asynchronous, f#, research, links, joinads
Read the complete article