5
votes

Does F# have an equivalent to OCaml's Async library? Specifically, the ability to easily make Deferred values and execute functions when they are filled?

In particular, I want to wait until a particular reference changes, and then do something. In OCaml, I'd do this by making an ivar and calling its read function; how can I do this in F#?

2
Asynchronous Workflows is a big selling point of F#. I can't say you can do a direct translation but you will almost certainly find something equivalent. - ChaosPandion
It sounds like you're asking about System.Lazy (see also the lazy keyword). - ildjarn
@ildjarn Hm. I'm not sure. That looks to me like "here's a thing, don't evaluate it until I'm ready"; I want "Start this thing, tell me when it's ready." - linkhyrule5
please clarify with a link or a code example so that we can either learn or help. - sgtz
@linkhyrule5 : That would be Task<T>. See also Async.AwaitTask, Async.StartAsTask, and Async.StartChildAsTask. - ildjarn

2 Answers

15
votes

Short answer

Yes, my Hopac library is a close relative of both Jane Street's Async library and the asynchronous workflows of F# among many others. Hopac is based on Concurrent ML (CML) and arguably (as in technical terms rather than as a matter of opinion) currently provides a more expressive programming model than either of those.

Longer answer

Jane Street's Async's Deferred is much like .Net's Task. Both are essentially comonadic abstractions with a monadic layer written on top.

In Hopac, the closest relative to a Deferred is actually a Promise. However, Hopac doesn't directly provide a monadic layer for Promises. Of course, you could easily write one, but I would advise to sit on it for awhile. Rather, Hopac provides the Job monad for encoding light-weight threads. This is analogous to how F#'s asynchronous workflows are defined and feels more natural and easier to reason about in my subjective opinion.

Jane Street's Async's Ivar is a close relative of Hopac's IVar. Both descend from the same lineage.

What makes CML and Hopac more expressive than Jane Street's Async and F#'s asynchronous workflows is the availability of combinators for synchronous events (CML) or alternatives (Hopac). Using those many kinds of concurrent protocols can be encapsulated as first-class, extensible (higher-order), selective operations.

CML's and Hopac's synchronous channels support simple rendezvous, which means that both ends of a communication agree when communication happens. This, in turn, has some interesting applications such as the ability to implement Multicast channels that support garbage collectable publish-subscribe style communications without need to explicitly cancel subscription (contrast with Rx IObservable-IObserver).

Specific answer

Here is an F# interactive session that first defines an IVar and then starts a concurrent Job that reads the value of the IVar and prints a message. Finally the IVar is written to with a value:

> let nameVar : IVar<string> = ivar () ;;
val nameVar : IVar<string>
> start (nameVar |>> fun who -> printfn "Hello, %s!" who) ;;
val it : unit = ()
> run (nameVar <-= "Vesa") ;;
val it : unit = ()
> Hello, Vesa!

To produce this output, F# interactive was started with the Hopac.fsx script.

0
votes

Does F# have an equivalent to OCaml's Async library?

F# has async built-in and more such as MailboxProcessor.

Specifically, the ability to easily make Deferred values and execute functions when they are filled?

.NET provides Task which does that.