How do I use F#'s built-in support for async operations classes exposing the Event-based Asynchronous Pattern such as WebClient class?
let Download(url : Uri) =
let client = new WebClient()
let html = client.DownloadString(url)
html
When I try to change this to use "let!" in an async block (say as described in Soma's recent post)
let Download(url : Uri) =
async {
let client = new WebClient()
let! html = client.DownloadStringAsync(url)
return html }
I get an error message:
Type constraint mismatch. The type unit is not compatible with type Async<'a> The type 'unit' is not compatible with the type 'Async<'a>'
Edit: I'm really asking about the general question of using *Async() methods, WebClient is just an easy example. Microsoft says "... you should expose asynchronous features using the Event-based Asynchronous Pattern [ as opposed to BeginFoo()/EndFoo() ] whenever possible ..." so I would think there should be an easy way to consume an arbitrary *Async() method from F#.
The WebClient.DownloadStringAsync method is part of the .NET framework. It'll raise an event to signal its progress, and its return type is unit, so you don't want to use it, and there's no advantage in wrapping it in an async object.
The F# PowerPack defines an extension method, val webclient.AsyncDownloadString : uri -> Async{string}:
let Download(url : Uri) =
async {
let client = new WebClient()
client.Encoding <- Encoding.GetEncoding("utf-8")
let! html = client.AsyncDownloadString(url)
return html }
Unfortunately, the choice of name clashes with the existing webclient method, which can understandably cause confusion. However, I believe all of the F# async extensions begin with Async*.
[Edit to add in response to comments:]
Usually, .NET uses the BeginFoo / EndFoo pattern for concurrency. If the types are right, you can just use Async.BuildPrimitive beginMethod endMethod, which will return an Async wrapper for the method.
Sometimes objects don't use this pattern, like the WebClient, and you actually have to use Async.AwaitEvent to wait for an event to be fired, or write your own loop to repeatedly check to see if a bool is set. Here's a nice article on converting events to Async objects.
For what its worth, if you have F# installed, you should also have the source code which will give you an idea of how the F# team implements their async extensions. On my machine, the relevant file is located at:
C:\Program Files\FSharp-1.9.6.16\source\fsppack\FSharp.PowerPack\AsyncOperations.fs
Related
let CreateEventSourcingConnection() =
task {
let connection =
let ipEndPoint = IPEndPoint(IPAddress.Loopback, 1113)
EventStoreConnection.Create(ipEndlPoint)
do! connection.ConnectAsync()
return connection
}
For task I get:
The value of constructor 'task' is not defined.
So, what is this and how can I define it?
I assume that the question is in the context of Logary, which gets the task computation builder from the TaskBuilder.fs NuGet package (as we can see from Paket references). The TaskBuilder.fs project is available here with some documentation.
So, task is a variable that represents an instance of the TaskBuilder computation builder. This is an F# computation expression, which lets you create computations that create the .NET Task<T> type as the result. Inside the computation expression, you can use let! and do! for the same purpose as await in C#, that is for waiting until some asynchronous operation completes (without blocking a thread):
task {
do! Console.Out.WriteLineAsync("Enter a filename:")
let! name = Console.In.ReadLineAsync()
use file = File.CreateText(name)
for i in Enumerable.Range(0, 100) do
do! file.WriteLineAsync(String.Format("hello {0}", i))
do! Console.Out.WriteLineAsync("Done")
return name
}
Here, WriteLineAsync and ReadLineAsync are .NET methods that return Task and we can use them as if they were returning just string or unit.
It is also worth adding that Logary is perhaps not the easiest piece of F# code to look into. It is very clever and nice, but relies on the HOPAC concurrency library which requires a fair bit of background knowledge and uses a number of fancy operators, which can make code quite tricky to understand. So if you are relatively new to F#, understanding HOPAC code might be a bit of a struggle!
I prefer to model business requirements as function types within a code base:
type Subscribe = SubscribeRequest -> Result<SubscribedCourier,ErrorDescription>
Then I implemented a function that complies with a function type:
let subscribe : Publish.Subscribe =
fun request ->
let subscribed = request |> toSubscribedCourier
...
Ok subscribed
Issue:
The above function is fine when implementing a unit test. However, when the above function needs to rely on an external system to complete its task, then I believe that the function requires an async modifier for that function signature.
As a result, I'm now obligated to update my function type to the following:
type Subscribe = SubscribeRequest -> Async<Result<SubscribedCourier,ErrorDescription>>
Thus, my actual function that needs to await an external system's response looks like this:
let subscribe : Publish.Subscribe =
fun request ->
async {
let subscribed = request |> toSubscribedCourier
let json = JsonConvert.SerializeObject subscribed
let buffer = Encoding.ASCII.GetBytes(json)
let message = Message(buffer)
let topicClient = new TopicClient("MyConnectionString","Subscription.subscribed")
do! topicClient.SendAsync(message) |> Async.AwaitTask
return Ok subscribed
}
Although, the above function type is correct for returning an Async result type, it's now a leaky abstraction for how the function executes. I really want to only specify business requirements through function types and have my functions map to those function types as if they were contacts.
Question:
In conclusion, how do I expose a function type as a business requirement without exposing its asynchronous dependency?
I don't know why you want to define a type alias for a function, but I do agree that if you want to implement a functional architecture, business logic shouldn't be asynchronous. In F# I think that it makes sense to view asynchronicity as implying impurity. You rarely need to return asynchronous workflows unless you're performing I/O.
I think that one should keep the domain model pure, so, as you write, returning an asynchronous workflow is a leaky abstraction.
You can often address the issue by refactoring to an impure-pure-impure sandwich. This also seems to be the case here. As far as I can tell, the work to actually put a message on a queue looks to be entirely generic. I suppose you could extract that into a helper function, like this:
let send x =
let json = JsonConvert.SerializeObject x
let buffer = Encoding.ASCII.GetBytes json
let message = Message buffer
let topicClient = new TopicClient ("MyConnectionString", "Subscription.subscribed")
do! topicClient.SendAsync message |> Async.AwaitTask
return Ok x
(I haven't tried to compile this, so there may be minor issues.)
You can now create the sandwich as a straightforward composition:
let sandwich = toSubscribedCourier >> send
(Again, this may not compile, but hopefully gets the point across.)
It's possible that there's little to no logic in toSubscribedCourier, but that's just the reality of things, then. As I've written in a recent article on the same general topic:
Once you remove all the accidental complexity, you uncover the essential complexity.
Perhaps there isn't much domain logic, but that fact is only laid bare once you start separating the pure functions from the impure actions.
Please unwrap these type signatures to help me understand why this doesn't work.
Then, if you have a solution, that would be great too.
I have this code and the agent.Post command has the signature Observer.Create<'T>(onNext: Action<'T>) : IObserver<'T>
let reservatinoRequestObserver = Observer.Create agent.Post
interface IHttpControllerActivator with
To my knowledge, this means that Observer.Create should take an Action with a single generic parameter and then return an IObserver.
Now the definition of Post is member MailboxProcessor.Post : message:'Msg ->unit
So... Post is a method, no? It is a method that takes a single parameter no? And it returns void no? So shouldn't it be a candidate for Observer.Create? Isn't that the exact specification of Action<'T>?
Well, somethings up, I get This function takes too many arguments, or is used in a context where a function is not expected:
Help me out... I freely admit I suck at F#
First, agent.Post returns unit, which is a different thing from void. F# will usually convert back and forth between void and unit for you, but they are not the same thing.
Second, F# functions do not implicitly convert to .NET delegates.
But there are some ways to do it:
You can explicitly create the delegate using its constructor:
let o = Observer.Create (new Action<_>( agent.Post ))
Lambdas are nicely wrapped too
let o = Observer.Create (fun msg -> agent.Post msg)
Use F# Rx-wrappers
Also there are a couple of F# wrappers/interop for Rx on nuget - just have a look, I think any will do
In C# awaiting the task awaiter is or ConfiguredTaskAwaitable is quite easy - just use await. What is the alternative for F#?
let! result = ...? doSomething().ConfigureAwait(false) ...?
F# async workflows and C# async-await keywords are two entirely separate mechanisms, and as such they are not directly compatible (though no doubt you can have wrappers that make that possible and most likely there are already wrappers like this around).
If you want to combine tasks with F# async workflow, you'd use the actual tasks rather than awaiters:
let! result = Async.AwaitTask task
If you have an API that gives you awaiters rather than tasks, here's a heavy-handed attempt at making an async out of a TaskAwaiter<'T>:
module Async =
let fromTaskAwaiter (awaiter: TaskAwaiter<'a>) =
async {
use handle = new SemaphoreSlim(0)
awaiter.OnCompleted(fun () -> ignore (handle.Release()))
let! _ = handle.AvailableWaitHandle |> Async.AwaitWaitHandle
return awaiter.GetResult()
}
I just want somehow to say "I want all methods in this project use [JavaScript]"
Manually annotation every method is annoying
F# 3 lets you mark a module with the ReflectedDefinition attribute (aka [JavaScript] in WebSharper) which marks all the methods underneath.
See More About F# 3.0 Language Features:
(Speaking of uncommon attributes, in F# 3.0, the
[< ReflectedDefinition >] attribute can now be placed on modules and
type definitions, as a shorthand way to apply it to each individual
member of the module/type.)
I think Phil's answer is the way to go - when you can mark an entire module or type, it does not add too much noise and it also allows you to distinguish between server-side and client-side code in WebSharper.
Just for the record, the F# compiler is open-source and so someone (who finds this issue important) could easily create branch that would add an additional command line attribute to override the setting. I think this is just a matter of adding the parameter and then setting the default value of the reflect flag in check.fs (here is the source on GitHub).
At the moment, the main F# repository does not accept contributions that add new features (see the discussion here), but it is certainly a good way to send a feature request to the F# team :-)
If you annotate all your code with the JavaScript attribute, the WebSharper compiler will try to translate everything to JavaScript. A rule of thumb in WebSharper development is to separate server-side and client-side code, so you can simply annotate the module/class containing client-side code instead of every function/member if you're targeting .NET 4.5.
namespace Website
open IntelliFactory.WebSharper
module HelloWorld =
module private Server =
[<Rpc>]
let main() = async { return "World" }
[<JavaScript>] // or [<ReflectedDefinition>]
module Client =
open IntelliFactory.WebSharper.Html
let sayHello() =
async {
let! world = Server.main()
JavaScript.Alert <| "Hello " + world
}
let btn =
Button [Text "Click Me"]
|>! OnClick (fun _ _ ->
async {
do! sayHello()
} |> Async.Start)
let main() = Div [btn]
type Control() =
inherit Web.Control()
[<JavaScript>]
override __.Body = Client.main() :> _