Combine Async and Option monads - asynchronous

In writing some code that works with a lot of nested async workflows lately I've found a pattern emerging that smells to me. A simple example:
let flip f x y = f y x
let slowInc x = async {
do! Async.Sleep 500
printfn "Here you go, %d" x
}
let verboseFun inp = async {
match List.tryFind (flip (>) 3) inp with
| Some x -> do! slowInc x
| _ -> ()
}
verboseFun [1..5] |> Async.RunSynchronously
The 'verboseFun' to me seems verbose but I can't think of a way to combine the Option and Async monads so it can be rewritten without the pattern match. I was thinking something like
let terseFun inp = async {
inp
|> List.tryFind (flip (>) 3)
|> Option.iterAsync slowInc
}
It just seemed to me that it's highly likely I just don't know what building blocks are available to achieve this.
EDIT: Extra clarification after Tomas' answer.
I was trying to adapt what would be trivial to me if everything was synchronous, e.g.,
let terseFun inp =
inp
|> List.tryFind (flip (>) 3)
|> Option.iter someSideEffectFunciton
to become part of nested async workflows. Originally I was thinking "just chuck a do! in there" so came up with
let terseFun inp = async {
inp
|> List.tryFind (flip (>) 3)
|> Option.iter (fun x -> async { do! someSideEffectFunciton x })
|> ignore
}
But it immediately smelled wrong to me because VS started demanding the ignore.
Hope this helps clarify.

The ExtCore library has a bunch of helper functions that let you work with asynchronous computations that return optional values, i.e. of type Async<'T option> and it even defines asyncMaybe computation builder for working with them.
I have not used it extensively, but from a few simple experiments I did, it looks like it is not as nicely integrated with the rest of F#'s async functionality as it perhaps could be, but if you want to go in this direction, ExtCore is probably the best library around.
The following is using the iter function from AsyncMaybe.Array (source is here). It is a bit ugly, because I had to make slowInc be of type Async<unit option>, but it is pretty close to what you asked for:
let slowInc x = async {
do! Async.Sleep 500
printfn "Here you go, %d" x
return Some ()
}
let verboseFun inp =
inp
|> List.tryFind (fun x -> 3 > x)
|> Array.ofSeq
|> AsyncMaybe.Array.iter slowInc
|> Async.Ignore
Aside, I also removed your flip function, because this is not generally recommended style in F# (it tends to make code cryptic).
That said, I think you don't really need an entire ExtCore library. It is hard to see what is your general pattern from just one example you posted, but if all your code snippets look similar to the one you posted, you can just define your own asyncIter function and then use it elsewhere:
let asyncIter f inp = async {
match inp with
| None -> ()
| Some v -> do! f v }
let verboseFun inp =
inp
|> List.tryFind (fun x -> x > 3)
|> asyncIter slowInc
The great thing about F# is that it is really easy to write these abstractions yourself and make them so that they exactly match your needs :-)

Related

F# Is there a Async.Sequential to match Async.Parallel?

F# has Async.Parallel with type signature seq<Async<'a>> -> Async<'a list>, which will take a seq of Async types, prep them to run in parallel, and output a single Async.
I was wondering if there is a similar Async.Sequential which has the same type signature, but runs each item in sequence one after the other? I feel like I must be missing something obvious?
I'd like to do something like the following:
async {
let! results =
myItems
|> List.map myAsynchronousOperation
|> Async.Sequential
... do something with results
}
I don't think there's one built in, but should be trivial to write your own:
let sequential s = async {
let results = ResizeArray()
for a in s do
let! result = a
results.Add(result)
return List.ofSeq results
}
Evaluating the items in a seq<Async<'a>> in-order and returning a list is effectively just a foldBack on the sequence where you want to evaluate the async before simply cons-ing it onto a list. While kvb's solution certainly works, you could also do it with a Seq.foldBack like so:
module Async =
let sequential s =
Seq.foldBack (fun cur acc -> async.Bind(cur, fun head ->
async.Bind(acc, fun tail -> async.Return(head :: tail)))) s (async.Return [])
With the release of F# 4.7 and FSharp.Core 4.7 Async.Sequential is now available "out-of-the-box".
Announcement: https://devblogs.microsoft.com/dotnet/announcing-f-4-7/
Source: https://github.com/dotnet/fsharp/blob/897afd3dad3bfe58a0495713e99a8094098c18c5/src/fsharp/FSharp.Core/async.fs#L1282
If one is willing to use the AsyncSeq library, then the following does what's needed in the given example:
async {
let! results =
myItems
|> AsyncSeq.ofSeq
|> AsyncSeq.mapAsync myAsynchronousOperation
|> AsyncSeq.toListAsync
... do something with results
}
Probably overkill if you're not already using AsyncSeq for other things though.

Function with type 'T -> Async<'T> like C#'s Task.FromResult

I'm playing around asynchronous programming and was wondering if there's a function that exists that can take a value of type 'T and transform it to an Async<'T>, similar to C#'s Task.FromResult that can take a value of type TResult and transform it to a Task<TResult> that can then be awaited.
If such a function does not exist in F#, is it possible to create it? I can kind of emulate this by using Async.AwaitTask and Task.FromResult, but can I do this by only using Async?
Essentially, I'd like to be able to do something like this:
let asyncValue = toAsync 3 // toAsync: 'T -> Async<'T>
let foo = async{
let! value = asyncValue
}
...or just async.Return
let toAsync = async.Return
let toAsync` x = async.Return x
moreover there is async.Bind (in tupled form)
let asyncBind
(asyncValue: Async<'a>)
(asyncFun: 'a -> Async<'b>) : Async<'b> =
async.Bind(asyncValue, asyncFun)
you could use them to make pretty complicated async computation without builder gist link
let inline (>>-) x f = async.Bind(x, f >> async.Return)
let requestMasterAsync limit urls =
let results = Array.zeroCreate (List.length urls)
let chunks =
urls
|> Seq.chunkBySize limit
|> Seq.indexed
async.For (chunks, fun (i, chunk) ->
chunk
|> Seq.map asyncMockup
|> Async.Parallel
>>- Seq.iteri (fun j r -> results.[i*limit+j]<-r))
>>- fun _ -> results
You can use return within your async expression:
let toAsync x = async { return x }

f# perform await async methods in list.iteri

I have the following code in F# 4.0
let processEscalation escalationAction (escalationEvents:UpdateCmd.Record list) =
printf "%A" Environment.NewLine
printf "Started %A" escalationAction
escalationEvents
|> List.iter ( fun x ->
printf "%A" Environment.NewLine
printf "escalation %A for with action: %A" x.incident_id escalationAction
service.PostAction(new Models.Action(x.incident_id, escalationAction, "escalated"))
|> Async.AwaitTask
|> ignore)
let ComposeEscalation() =
let escalationlevels = ["ESC1 REACHED"; "ESC2 REACHED"; "ESC3 REACHED"]
escalationlevels
|> List.map getEscalationEvents
|> List.iteri (fun i x -> processEscalation escalationlevels.[i] x)
where the following line is a call to a C# async method that that returns Task
service.PostAction(new Models.Action(x.incident_id, escalationAction, "escalated"))
The compose escalation method calls the processEscalation three times.
However, the second call starts before the first call is complete.
How can I make sure that the the last line, list.iteri awaits and processes them sequentially?
Perhaps the processEscalation should be in an async computation expression?
What Async.AwaitTask does is that it returns an Async computation that can be used to wait for the task to complete. In your case, you never do anything with it, so the loop just proceeds to the next iteration.
You want something like this:
service.PostAction(new Models.Action(x.incident_id, escalationAction, "escalated"))
|> Async.AwaitTask
|> Async.RunSynchronously
|> ignore
This should have the effect you expect, though certainly there are nicer, more composable ways of expressing such logic.
Edit: What I meant was something like this, a counterpart to the core Async.Parallel function:
module Async =
let sequential (asyncs: seq<Async<'t>>) : Async<'t []> =
let rec loop acc remaining =
async {
match remaining with
| [] -> return Array.ofList (List.rev acc)
| x::xs ->
let! res = x
return! loop (res::acc) xs
}
loop [] (List.ofSeq asyncs)
Then you can do something along these lines:
escalationEvents
// a collection of asyncs - note that the task won't start until the async is ran
|> List.map (fun x ->
async {
let task =
service.PostAction(new Models.Action(x.incident_id, escalationAction, "escalated"))
return! Async.AwaitTask task
})
// go from a collection of asyncs into an async of a collection
|> Async.sequential
// you don't care about the result, so ignore it
|> Async.Ignore
// now that you have your async, you need to run it in a way that makes sense
// in your context - Async.Start could be another option.
|> Async.RunSynchronously
The upside here is that instead of bundling everything into a single loop, you've split the computation into well-delimited stages. It's easy to follow and refactor (e.g. if you need to process those events in parallel instead, you just switch out one step in the pipeline).

"Subsetting" a dictionary in F#

I'm a beginner in F# and I'm trying to write a function to subset a dictionary given list, and return the result.
I tried this, but it doesn't work.
let Subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = dict.Clear
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.TryGetValue k) )
|> List.iter (fun s -> z.Add s)
|> List.iter (fun s -> z.Add s);;
--------------------------------------^^^
stdin(597,39): error FS0039: The field, constructor or member 'Add' is not defined
Perhaps there is a native function in F# to do that ?
thanks
EDIT
thanks to #TheInnerLight for his answer below
can you just educate me a bit more, and tell me how i should adapt that function if i want to return the original variable being modified ?
(of course it would be possible to go from where we call that function, call it with a temp variable, and reassign)
You have written:
let z = dict.Clear
z is of type unit->unit yet you are calling z.Add.
I suspect you want to write
let subset (dict:Dictionary<'T,'U>) (sub_list:list<'T>) =
let z = Dictionary<'T,'U>() // create new empty dictionary
sub_list |> List.filter (fun k -> dict.ContainsKey k)
|> List.map (fun k -> (k, dict.[k]) )
|> List.iter (fun s -> z.Add s)
z
TryGetValue is going to return something of type bool*'U in F#, which I suspect you don't want if already filtering by ContainsKey so you probably want to look up directly with dict.[k].
Note that Dictionary is a mutable collection so if you were to actually call dict.Clear(), it wouldn't return a new empty dictionary, it would mutate the existing one by clearing all elements. The immutable F# data structure usually used for key-value relationships is Map, see https://msdn.microsoft.com/en-us/library/ee353880.aspx for things you can do with Map.
Here is a map version (this is the solution I recommend):
let subset map subList =
subList
|> List.choose (fun k -> Option.map (fun v -> k,v) (Map.tryFind k map))
|> Map.ofList
Edit (in response to the question edit about modifying the input variable):
It's possible to update an existing dictionary using the destructive update operator <- on a mutable variable.
Option 1:
let mutable dict = Dictionary<Key,Value>() // replace this with initial dictionary
let lst = [] // list to check against
dict <- sublist dict lst
Likewise, my first function could be changed to perform only a side effect (removing unwanted elements).
Option 2:
let subset (d : System.Collections.Generic.Dictionary<'T,'U>) (sub_list : list<'T>) =
sub_list
|> List.filter (d.ContainsKey >> not)
|> List.iter (d.Remove >> ignore)
For an F# beginner I don't really recommend Option 1 and I really don't recommend Option 2.
The functional approach is to favour immutable values, pure functions, etc. This means you will be better off thinking of your functions as defining data transformations rather than as defining a list of instructions to be performed.
Because F# is a multi-paradigm language, it's easy to fall back on the imperative in the early stages but you will probably gain the most from learning your new language if you force yourself to adopt the standard paradigm and idioms of that language even if those idioms feel strange and uncomfortable to begin with.
The immutable data structures like Map and list are pretty efficient at sharing data as well as providing good time complexity so these are really the go-to collections when working in F#.

Async workflows in F# - Execute in parallel and do not wait for the result

Is it possible to use Async workflows in F#, execute multiple async operations in parallel but do not wait for the result ? Does it makes sense ? :)
So instead of this :
let runAll() =
urlList
|> Seq.map fetchAsync
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
Do something like this :
let runAll() =
urlList
|> Seq.map fetchAsync
|> Async.Parallel
|> ignore
Of course I need to start the the operation, so I tried just starting the execution of the async operation inside the fetchAsync function, it then works just by calling the function :
let runAll() =
urlList
|> Seq.map fetchAsync
|> ignore
But then, my code is no longer parallelized :/
I may have missed something obvious.
Thanks for the help!
My understanding is you want to start up a whole stack of Async operations but then do something else without waiting for them to complete. In this case, you want to use Async.Start like this:
let runAll() =
urlList
|> List.map Async.Start

Resources