-
Notifications
You must be signed in to change notification settings - Fork 28
Description
The types:
type AsyncArrow<'a, 'b> = 'a -> Async<'b>
type AsyncFilter<'a, 'b, 'c, 'd> = AsyncArrow<'a, 'b> -> AsyncArrow<'c, 'd>
type AsyncFilter<'a, 'b> = AsyncArrow<'a, 'b> -> AsyncArrow<'a, 'b>The async arrow type can have many interpretations and is particularly well suited at representing an async request-reply protocol. Data driven services are usually a composition of various request-reply interactions and it can be useful to reify the type.
The supported operations would be all those of arrows as seen here but also many others specific to Async and other types. Consider operations such as:
/// Invokes arrow g and then invokes f if successful (Choice1Of2).
val tryBefore (g:AsyncArrow<'a, Choice<'a, 'c>>) (f:AsyncArrow<'a, 'b>) : AsyncArrow<'a, Choice<'b, 'c>>
/// Creates an arrow which propagates its input into the output.
val strength (f:AsyncArrow<'a, 'b>) : AsyncArrow<'a, 'a * 'b>
/// Creates an arrow which filters inputs to the specified arrow.
val filterAsync (p:AsyncArrow<'a, bool>) (df:Async<'b>) (f:AsyncArrow<'a, 'b>) : AsyncArrow<'a, 'b>Async filters represent mappings between arrows. A filter can be use to inject various cross-cutting concerns. For example, a timing filter:
let timing (log:NLog.Logger) : AsyncFilter<_,_,_,_> =
fun (f:AsyncArrow<'a, 'b>) a -> async {
let sw = System.Diagnostics.Stopwatch.StartNew()
let! res = f a
sw.Stop()
log.Trace("Time Elapsed={0}", sw.ElapsedMilliseconds)
return res
}A filter can also change the input/output type of an arrow. This can be used for layering a JSON codec onto a request/reply protocol, for instance.
type AsyncSink<'a> = AsyncArrow<'a, unit>A sink can be used to represent functions which are run solely for the side-effects. An example operation:
let mergeAllPar (ss:seq<AsyncSink<'a>>) : AsyncSink<'a> =
fun a -> ss |> Seq.map ((|>) a) |> Async.Parallel |> Async.Ignore