Using C# - ASP.NET MVC 4, I can define an async controller action like:
public async Task<ActionResult> IndexWorks()
{
var data = await DownloadAsync("http://stackoverflow.com");
return Content(data);
}
Is there a way to do something similar, using F#?
I'm aware of that I could use the AsyncManager approach. I'm also aware of that #Tomas Petricek have made a quite neat AsyncActionBuilder, but it just feels like a lot of boilerplate, compared to the C# approach.
async/await uses Tasks, so you'll need to convert back and forth between Task object and F# Async objects. To convert from Task to Async, use Async.AwaitTask. To do the opposite use Async.StartAsTask. Your example becomes:
member x.IndexWorks() =
async {
let! data = Async.AwaitTask (DownloadAsync "http://stackoverflow.com")
return x.Content(data)
} |> Async.StartAsTask
Alternatively, instead of using the async computation expression, you can use a computation expression that works for Tasks out of the box. There's one in FSharpx:
let task = FSharpx.Task.TaskBuilder()
(...)
member x.IndexWorks() = task {
let! data = DownloadAsync "http://stackoverflow.com"
return x.Content(data)
}
It actually seems like a fellow programmer, Dmitry Morozov have made such thing possible. He have made a custom AsyncWorkflowController that makes it possible to return Async<ActionResult> from an ActionResult. The code for the AsyncWorkFlowController can be found at http://fssnip.net/5q.
However, his implementation makes it very difficult to debug, due to the fact that the stack trace wont be preserved when rethrowen in the custom controller. Therefore I've made a little change to make this possible:
member actionDesc.EndExecute(asyncResult) =
match endAsync'.Value(asyncResult) with
| Choice1Of2 value -> box value
| Choice2Of2 why ->
// Preserve the stack trace, when rethrow
ExceptionDispatchInfo.Capture(why).Throw()
obj() (* Satisfy return value *) } } }
Also I've changed the following line: new ReflectedControllerDescriptor(controllerType),
to new ReflectedAsyncControllerDescriptor(controllerType) - However this change is purely optional, as it wont make any difference. I just found it more logical to use the Async one.
The full code would then be:
open System
open System.Web.Mvc
open System.Web.Mvc.Async
open System.Runtime.ExceptionServices
open Unchecked
type AsyncWorkflowController() =
inherit AsyncController()
override __.CreateActionInvoker() =
upcast { new AsyncControllerActionInvoker() with
member __.GetControllerDescriptor(controllerContext) =
let controllerType = controllerContext.Controller.GetType()
upcast { new ReflectedAsyncControllerDescriptor(controllerType) with
member ctrlDesc.FindAction(controllerContext, actionName) =
let forwarder = base.FindAction(controllerContext, actionName) :?> ReflectedActionDescriptor
if(forwarder = null || forwarder.MethodInfo.ReturnType <> typeof<Async<ActionResult>>) then
upcast forwarder
else
let endAsync' = ref (defaultof<IAsyncResult -> Choice<ActionResult, exn>>)
upcast { new AsyncActionDescriptor() with
member actionDesc.ActionName = forwarder.ActionName
member actionDesc.ControllerDescriptor = upcast ctrlDesc
member actionDesc.GetParameters() = forwarder.GetParameters()
member actionDesc.BeginExecute(controllerContext, parameters, callback, state) =
let asyncWorkflow =
forwarder.Execute(controllerContext, parameters) :?> Async<ActionResult>
|> Async.Catch
let beginAsync, endAsync, _ = Async.AsBeginEnd(fun () -> asyncWorkflow)
endAsync' := endAsync
beginAsync((), callback, state)
member actionDesc.EndExecute(asyncResult) =
match endAsync'.Value(asyncResult) with
| Choice1Of2 value -> box value
| Choice2Of2 why ->
// Preserve the stack trace, when rethrow
ExceptionDispatchInfo.Capture(why).Throw()
obj() (* Satisfy return value *) } } }
Usage:
type TestController() =
inherit AsyncWorkflowController()
member x.IndexWorks() = async {
let startThread = Thread.CurrentThread.ManagedThreadId
let! data = asyncDownload "http://stackoverflow.com"
let endThread = Thread.CurrentThread.ManagaedThreadId
return ContentResult(Content = "Start = %i | End = %i" startThread endThread) :> ActionResult }
And to confirm that it actually does everything async, and is not blocking any thread from the ASP.NET Pool, use:
member x.IndexWorks() = async {
let startThread = Thread.CurrentThread.ManagedThreadId
let! data = asyncDownload "http://stackoverflow.com"
let endThread = Thread.CurrentThread.ManagaedThreadId
return ContentResult(Content = "Start = %i | End = %i" startThread endThread) :> ActionResult }
The start and end thread will differ, hence the start thread was put back into the pool, and a new was returned when the async operation had completed.
I think there might be a bunch of people trying to do something like
type SomeController() =
inherit ApiController()
member x.Get() =
let data = Download("http://stackoverflow.com")
x.Ok(data) :> IHttpActionResult // Using built in Ok, BadRequest, etc.
Where type Get() = unit -> Task<IHttpActionResult> as expected from a C# WebApi Controller
If you try to do it as the accepted answer suggests (while trying to use the built-in Ok, BadRequest, etc. methods) you run into
can't access protected members from within a lambda
To solve this I used the ExtensionMethods directly rather than try to do contort between async {} and Task that MVC is expecting
type SomeController() =
inherit ApiController()
member x.Get() = async {
let! data = DownloadAsync("http://stackoverflow.com") |> Async.AwaitTask
return System.Web.Http.Results.OkNegotiatedContentResult(data, x) :> IHttpActionResult // Pass in 'this' pointer (x) into extension method along with data
} |> Async.StartAsTask
This with the additional upcast :> IHttpActionResult you can also return different behavior BadRequest, etc from your model and still have it run async and the type signatures should work out and compile cleanly
Related
I am trying to learn F# and am in the process of converting some C# code to F#.
I have the following C# method:
public async Task<Foo> GetFooAsync(byte[] content)
{
using (var stream = new MemoryStream(content))
{
return await bar.GetFooAsync(stream);
}
}
Where bar is some private field and GetFooAsync returns a Task<Foo>.
How does this translate to F#?
Here is what I currently have:
member public this.GetFooAsync (content : byte[]) =
use stream = new MemoryStream(content)
this.bar.GetFooAsync(stream)
Which returns a Task.
In F#, asynchrony is represented by the async computation builder, which is not an exact analog of Task, but can generally be used in place of one:
member public this.GetFooAsync (content : byte[]) =
async {
use stream = new MemoryStream(content)
return! this.bar.GetFooAsync(stream) |> Async.AwaitTask
}
|> Async.StartAsTask
If you are converting async/await-intensive C# code to F#, it might get cumbersome because of the difference between F#'s async and Task and the fact that you always have to call Async.AwaitTask
To avoid that you can use FSharpx library, which has a task computation expression.
let tplAsyncMethod p = Task.Run (fun _ -> string p)
// awaiting TPL method inside async computation expression
let asyncResult = async {
let! value1 = tplAsyncMethod 1 |> Async.AwaitTask
let! value2 = tplAsyncMethod 2 |> Async.AwaitTask
return value1 + value2
}
// The same logic using task computation expression
open FSharpx.Task
let taskResult = task {
let! value1 = tplAsyncMethod 1
let! value2 = tplAsyncMethod 2
return value1 + value2
}
The result of asyncResult is Async<string> and the result of taskResult is Task<string>.
Considering the following
type MyClass () =
member x.ReadStreamAsync(stream:Stream) =
async {
let tcs = new TaskCompletionSource<int>()
let buffer = Array.create 2048 0uy
let! bytesReadCount = stream.ReadAsync(buffer, 0, buffer.Length) |> Async.AwaitTask
if bytesReadCount > 0 then
for i in 0..bytesReadCount do
if buffer.[i] = 10uy then
tcs.SetResult(i)
// Omitted more code to handle the case if 10uy is not found..
return tcs.Task
}
The code reads from a stream until in meets a certain character (represented by a byte value) at which point the task returned by the method completes.
The function signature of DoSomethingAsync is unit -> Async<Task<int>>, but I would like it to be unit -> Task<int> such that it can be used more generally in .NET.
Can this be done in F# using an asynchronous expression, or do I can to rely more on the Task constructs of .NET?
Given that you don't actually use the async workflow for anything in your example, the easiest solution would be to forgo it entirely:
member x.DoSomethingAsync() =
let tcs = new TaskCompletionSource<int>()
Task.Delay(100).Wait()
tcs.SetResult(10)
tcs.Task
This implementation of DoSomethingAsync has the type unit -> Task<int>.
It's not clear to me exactly what you're trying to do, but why don't you just do the following?
member x.DoSomethingAsync() =
async {
do! Async.Sleep 100
return 10 } |> Async.StartAsTask
This implementation also has the type unit -> Task<int>.
Based on the updated question, here's a way to do it:
member x.DoSomethingAsync(stream:Stream) =
async {
let buffer = Array.create 2048 0uy
let! bytesReadCount =
stream.ReadAsync(buffer, 0, buffer.Length) |> Async.AwaitTask
if bytesReadCount > 0
then
let res =
[0..bytesReadCount]
|> List.tryFind (fun i -> buffer.[i] = 10uy)
return defaultArg res -1
else return -1
}
|> Async.StartAsTask
The DoSomethingAsync function has the type Stream -> System.Task<int>. I didn't know what to do in the else case, so I just put -1, but I'm sure you can replace it with something more correct.
For a project I am working on I need a global variable(technically I don't, I could build it and then pass it to every single function call, and let every single function call know about it, but that seems just as hacky, less readable and more work.)
The global variables are look up tables(endgame, opening book and transpositions/cache) for a game.
The fact that some of the code may lose some of it's indempotent behavior is actually the point(speedups) in short, yes I know global mutable state is bad, it's really worth it in this case(10x+ performance improvement)
So here's the question, "build a singleton or use a static value in a static class with combinators"
They are effectively identical but I am curious what people have done before on this sort of problem
Or alternatively, should I be passing the thing around to everyone(or at least a reference to it anyways),is that really the best answer?
Here is a solution similar to the one posted by #Yin Zhu's, but using abstract types to specify a usage interface for the mutable value, a local definition to encapsulate it and object literals to provide an implementation (this is taken from Expert F#--which is co-authored by Don Syme):
type IPeekPoke =
abstract member Peek: unit -> int
abstract member Poke: int -> unit
let makeCounter initialState =
let state = ref initialState
{ new IPeekPoke with
member x.Poke(n) = state := !state + n
member x.Peek() = !state }
You can also do it with static fields, like this:
type Common() =
static let mutable queue : CloudQueue = null
static let mutable storageAccount : CloudStorageAccount = null
static member Queue
with get() = queue
and set v = queue <- v
static member StorageAccount
with get() = storageAccount
and set v = storageAccount <- v
In another module, just:
open Common
Common.Queue <- xxxx
here is the convention used in F# PowerPack Matrix library (\src\FSharp.PowerPackmath\associations.fs):
// put global variable in a special module
module GlobalAssociations =
// global variable ht
let ht =
let ht = new System.Collections.Generic.Dictionary<Type,obj>()
let optab =
[ typeof<float>, (Some(FloatNumerics :> INumeric<float>) :> obj);
typeof<int32>, (Some(Int32Numerics :> INumeric<int32>) :> obj);
...
typeof<bignum>, (Some(BigRationalNumerics :> INumeric<bignum>) :> obj); ]
List.iter (fun (ty,ops) -> ht.Add(ty,ops)) optab;
ht
// method to update ht
let Put (ty: System.Type, d : obj) =
// lock it before changing
lock ht (fun () ->
if ht.ContainsKey(ty) then invalidArg "ty" ("the type "+ty.Name+" already has a registered numeric association");
ht.Add(ty, d))
What is the F# equivalent of the following C# code? Specifically, I need to check if an event is being handled.
protected virtual void OnClicked(ClickEventArgs e) {
if (this.Clicked != null) //how can I perform this check in F#
this.Clicked(this, e);
}
Okay, I think I figured this thing out. Taking a cue from Don Syme's blog, specifically the section "The Implementation of the IEvent Module."
Instead of the following:
let validationFailedEvent = new Event<DataValidationEventHandler, DataValidationEventArgs>()
I had to implement IEvent myself and create a variable to hold the invocation list:
let mutable listeners: Delegate = null
let validationFailedEvent = { new IEvent<DataValidationEventHandler, DataValidationEventArgs> with
member x.AddHandler(d) =
listeners <- Delegate.Combine(listeners, d)
member x.RemoveHandler(d) =
listeners <- Delegate.Remove(listeners, d)
member x.Subscribe(observer) =
let h = new Handler<_>(fun sender args -> observer.OnNext(args))
(x :?> IEvent<_,_>).AddHandler(h)
{ new System.IDisposable with
member x.Dispose() = (x :?> IEvent<_,_>).RemoveHandler(h) } }
Then, to check if there are listeners, and, if not, raise an exception:
member private x.fireValidationFailedEvent(e:DataValidationEventArgs) =
match listeners with
| null -> failwith "No listeners"
| d -> d.DynamicInvoke([| box x; box e |])
An alternative way to implement RequiresSubscriptionEvent is to build on top of the existing Event functionality (using composition) and just add a counter that counts the number of registered handlers and add a property HasListeners (or even publish the number of listeners if you wanted...)
This makes the code a bit easier to use and hopefuly also safer, because if you don't check whether it has any listneres, it will still work as the usual F# code. And if you want to perform the check, you can...
type RequiresSubscriptionEvent<_>() =
let evt = new Event<_>()
let mutable counter = 0
let published =
{ new IEvent<_> with
member x.AddHandler(h) =
evt.Publish.AddHandler(h)
counter <- counter + 1;
member x.RemoveHandler(h) =
evt.Publish.RemoveHandler(h)
counter <- counter - 1;
member x.Subscribe(s) =
let h = new Handler<_>(fun _ -> s.OnNext)
x.AddHandler(h)
{ new System.IDisposable with
member y.Dispose() = x.RemoveHandler(h) } }
member x.Trigger(v) = evt.Trigger(v)
member x.Publish = published
member x.HasListeners = counter > 0
Sample usage:
type Demo() =
let evt = new RequiresSubscriptionEvent<_>()
[<CLIEvent>]
member x.OnSomething = evt.Publish
member x.FooThatFiresSomething() =
if evt.HasListeners then
evt.Trigger("foo!")
else
printfn "No handlers!"
Even though this isn't a part of standard F# libraries, it shows the great advantage of F# first class events. If there is some missing functionality, you can simply implement it yourself!
Typically, you don't need to do that check in F# (the event infrastructure checks for you):
type T() =
let ev = new Event<_>()
[<CLIEvent>]
member x.Event = ev.Publish
member x.OnClicked() =
ev.Trigger()
I followed kvb's suggestion and put this logic in a class. I copied Event from the F# sources and added a Handled property, which checks if the Delegate is null. I tried adding to, then removing handlers from the event to make sure it gets set back to null, and indeed it does.
type EventEx<'Delegate,'Args when 'Delegate : delegate<'Args,unit> and 'Delegate :> System.Delegate >() =
let mutable multicast : System.Delegate = null
static let argTypes =
let instanceBindingFlags = BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.DeclaredOnly
let mi = typeof<'Delegate>.GetMethod("Invoke",instanceBindingFlags)
mi.GetParameters() |> (fun arr -> arr.[1..]) |> Array.map (fun p -> p.ParameterType)
member x.Handled = (multicast <> null)
member x.Trigger(sender:obj,args:'Args) =
match multicast with
| null -> ()
| d ->
if argTypes.Length = 1 then
d.DynamicInvoke([| sender; box args |]) |> ignore
else
d.DynamicInvoke(Array.append [| sender |] (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields(box args))) |> ignore
member x.Publish =
{ new IEvent<'Delegate,'Args> with
member x.AddHandler(d) =
multicast <- System.Delegate.Combine(multicast, d)
member x.RemoveHandler(d) =
multicast <- System.Delegate.Remove(multicast, d)
member e.Subscribe(observer) =
let h = new Handler<_>(fun sender args -> observer.OnNext(args))
(e :?> IEvent<_,_>).AddHandler(h)
{ new System.IDisposable with
member x.Dispose() = (e :?> IEvent<_,_>).RemoveHandler(h) } }
This article here http://geekswithblogs.net/Erik/archive/2008/05/22/122302.aspx says you do not need to check for null events in F#, though I don't know what his reference is.
This article http://blogs.msdn.com/dsyme/articles/FSharpCompositionalEvents.aspx by Don Symes goes into F# events in quite a bit of detail. It looks like events are not owned by the class in F#
From the above,
it is that events are now first-class
values in the F# langauge. Indeed,
events are not a separate notion at
all in the language design, rather,
events are just values of type
Microsoft.FSharp.Idioms.IEvent<_>, and
.NET events are effectively just
properties of this type.
And
One of the restrictions of C# is that
events can only exist as members
within classes. With the F# model,
new event values can be created just
as values as part of any expression.
Is it possible to call a method on a returned object using the pipeline infix operator?
Example, I have a .Net class (Class1) with a method (Method1). I can currently code it like this:
let myclass = new Class1()
let val = myclass.Method1()
I know I could also code it as such
let val = new Class1().Method1()
However I would like to do be able to pipeline it (I am using the ? below where I don't know what to do):
new Class1()
|> ?.Method1()
Furthermore, say I had a method which returns an object, and I want to only reference it if that method didn't return null (otherwise bail?)
new Class1()
|> ?.Method1()
|> ?? ?.Method2()
Or to make it clearer, here is some C# code:
public void foo()
{
var myclass = new Class1();
Class2 class2 = myclass.Method1();
if (class2 == null)
{
return;
}
class2.Method2();
}
You can define something similar to your (??) operator fairly easily (but operators can't start with a question mark):
let (~??) f x =
if (x <> null) then
f x
Unfortunately, your pipelined code will need to be a bit more verbose (also, note that you can drop the new keyword for calling constructors):
Class1()
|> fun x -> x.Method1()
Putting it all together:
Class1()
|> fun x -> x.Method1()
|> ~?? (fun x -> x.Method2())
Using a custom operator as 'kvb' suggests is definitely an option. Another approach that you may find interesting in this case is to define your own 'computation expression' that automatically performs the check for null value at every point you specify. The code that uses it would look like this:
open System.Windows.Forms
// this function returns (0) null, or (1) btn whose parent is
// null or (2) button whose parent is not null
let test = function
| 1 -> new Button(Text = "Button")
| 2 -> new Button(Text = "Button", Parent = new Button(Text = "Parent"))
| _ -> null
let res =
safe { let! btn = test(2) // specify number here for testing
// if btn = null, this part of the computation will not execute
// and the computation expression immediately returns null
printfn "Text = %s" btn.Text
let! parent = btn.Parent // safe access to parent
printfn "Parent = %s" parent.Text // will never be null!
return parent }
As you can see, when you want to use a value that can potentially be 'null', you use let! inside the computation expression. The computation expression can be defined so that it immediately returns null if the value is null and runs the rest of the computation otherwise. Here is the code:
type SafeNullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) =
if v = null then null else f(v)
let safe = new SafeNullBuilder()
BTW: If you want to learn more about this, it is very similar to 'Maybe' monad in Haskell (or computation working with F# option type).