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!
Related
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.
It seems like there are two ways to return errors in an async workflow: raise and Result.
let willFailRaise = async {
return raise <| new Exception("oh no!")
}
let willFailResult = async {
return Result.Error "oh no!"
}
For the caller, the handling is a bit different:
async {
try
let! x = willFailRaise
// ...
with error ->
System.Console.WriteLine(error)
}
async {
let! maybeX = willFailResult
match maybeX with
| Result.Ok x ->
// ...
| Result.Error error ->
System.Console.WriteLine(error)
}
My questions are:
What are the advantages / disadvantages of each approach?
Which approach is more idiomatic F#?
It depends on what kind of error we are talking about. Basically there are three kinds:
Domain errors (e.g. user provided invalid data, user with this email is already registered, etc.)
Infrastructure errors (e.g you can't connect to another microservice or DB)
Panics (e.g. NullReferenceExceptionor StackOverflowException etc.), which are caused by programmers' mistakes.
While both approaches can get the job done, usually your concern should be to make your code as self-documented and easy-to-read as possible. Which means the following:
Domain errors: definitely go for Result. Those "errors" are expected, they are part of your workflow. Using Result reflects your business rules in function's signature, which is very useful.
Infrastructure failures: it depends. If you have microservices, then probably those failures are expected and maybe it would be more convenient to use Result. If not -- go for exceptions.
Panics: definitely Exception. First of all, you can't cover everything with Result, you gonna need global exception filter either way. Second thing -- if you try to cover all possible panics - code becomes a nasty disaster extremely fast, that will kill the whole point of using Result for domain errors.
So really this has nothing to do with Async or C# interop, it's about code readability and maintainability.
As for C# iterop -- don't worry, Result has all the methods to help, like IsError and so on. But you can always add an extension method:
[<AutoOpen>]
module Utils =
type Result<'Ok, 'Error> with
member this.Value =
match this with
| Ok v -> v
| Error e -> Exception(e.ToString()) |> raise
This is one of the many aspects of F# programming that suffers from the mind-split at the core of the language and its community.
On one hand you have "F# the .NET Framework language" where exceptions are the mechanism for handling errors, on the other - "F# the functional programming language" that borrows its idioms from the Haskell side of the world. This is where Result (also known as Either) comes from.
The answer to the question "which one is idiomatic" will change depending who you ask and what they have seen, but my experience has taught me that when in doubt, you're better off using exceptions. Result type has its uses in moderation, but result-heavy programming style easily gets out of hand, and once that happens it's not a pretty sight.
Raise
Advantages
Better .NET interop as throwing exceptions is fairly common in .NET
Can create custom Exceptions
Easier to get the stack trace as it's right there
You probably have to deal with exceptions from library code anyways in most standard async operations such as reading from a webpage
Works with older versions of F#
Disadvantages:
If you aren't aware of it potentially throwing an exception, you might not know to catch the exception. This could result in runtime explosions
Result
Advantages
Any caller of the async function will have to deal with the error, so runtime explosions should be avoided
Can use railway oriented programming style, which can make your code quite clean
Disadvantages
Only available in F# 4.1 or later
Difficult for non-F# languages to use it
The API for Result is not comprehensive.
There are only the functions bind, map, and mapError
Some functions that would be nice to have:
bimap : ('TSuccess -> 'a) -> ('TError -> 'e) -> Result<'TSuccess,'TError> -> Result<'a, 'e>
fold : ('TSuccess -> 'T) -> ('TError -> 'T) -> Result<'TSuccess, 'TError> -> 'T
isOk
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()
}
Given i have the IO function:
// this can either be IO or some other side effect
//that makes the function less pure
printf "HI"
I want to test that IO was called correctly. An imperative solution for testing that IO was called correctly would be to wrap the IO statement in an object, mock the object, pass the object in using dependency injection, and verify the correct method was called with the correct parameters. I wonder if instead of using dependency injection to test F#, a better way would be checking the output of the function (by asserting that the correct value or function is returned) and stub out the IO call; therefore making the function pure again by eliminating the side effect of an IO call.
I am considering wrapping all IO in a special module like so.
let MyPrint print statement = print statement ; statement
so that i can stub out the IO function and assert in my tests that the correct operation occurred like so:
code under test:
let PrintHi = fun(print) -> MyPrint print "HI"
let DoNothing = fun(print) -> ()
let DoIf conditional =
if conditional then PrintHi
else DoNothing
FsUnit:
[<Test>] member test.
let printStub value = ()
``Test Hi Is Printed When TRUE`` ()=
let testedFunc = DoIf true
testedFunc(printStub) |> should equal PrintHi(printStub)
Is this a good way to test IO side effects? Is there a better way? Please keep in mind that my goal is to test any IO, not just a print statement.
Generally speaking, you'll want to separate pure code from impure (side-effecting) code; and keep code as pure as possible.
I recommend reading these articles about it, they're written for other functional languages but the code they use is simple and the concepts are well explained and can be easily applied in F# (and many other languages for that matter):
Introduction to QuickCheck (Haskell wiki)
How to write a functional program with IO, mutation, and other effects
You could write a wrapper function which temporarily redirects stdout during the call to a function and returns the written values along with the function result:
let testPrintf f arg =
let oldOut = System.Console.Out
use out = new System.IO.StringWriter()
System.Console.SetOut(out)
let res = f arg
System.Console.SetOut(oldOut)
(res, out.GetStringBuilder().ToString())
I guess you don't really want to check if printf works as expected (to you?) - I think you want to know if there is some more functional way than DI to get testable results.
The answer is twofold:
First: F# is a mixed languague with a big OOP part - so yes I would do your standard DI pattern with interfaces and all that.
Second: instead of using this pattern you can allways use higher-order functions to pass in functions that does for example the IO - in your case something like
let myFunctionUsingIO (printer : string -> unit) (whateverparamsYouNeed) = ...
and then test this by passing a printer that Asserts whatever your requirements are - but in the end thats the same as having a interface with only one (unnamed) method - so the difference is very small.
PS: if you only interessted in the return value - just do normal unit-testing - if you write your functions pure there is no need to test anything different, but then your example was ... well poor, because printf is the opposite of pure...
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