I am looking for a way to define Parameterless lambda expressions in F#, much like the following C# example.
var task = () => {
int x = 3;
DoSomething(x);
}
I tried the following
let task = fun _ ->
let x = 3
doSomething x
It compiles but it gives me task : ('a -> unit) what I am actually looking for is task : (unit -> unit)
The MSDN Documentation does not talk about this. What am I missing here ?
it's just
let task = fun () -> // whatever you need
you example would be:
let task = fun () ->
let x = 3
DoSomething(3)
assuming DoSomething is of type int -> unit - if it returns something else you need
let task = fun () ->
let x = 3
DoSomething(3) |> ignore
to get type unit -> unit
Remark:
Usually you don't write let task = fun () -> ... but just let task() = ...
The thing you missed:
if you write fun _ -> () you are saying you want to take some parameter that you don't mind about - so F# will take the most general (being named 'a here) - this would include unit!
() is the only value of type unit (more or less void from C# ... but a true type in F#)
Related
Have I correctly implemented map for Task?
let map continuation (t: Task<'A>) =
t.ContinueWith(fun (antecedent: Task<'A>) ->
if antecedent.Status <> TaskStatus.Canceled &&
antecedent.Status <> TaskStatus.Faulted then
continuation antecedent.Result
else
raise antecedent.Exception // must I?
)
I got the TaskStatus checks from the docs. I feel most uncertain about raise antecedent.Exception, but I can't think of another way to handle it.
As background, yes I'm aware of Async, but my current stack uses Entity Framework and Blazor, so I have a backend that uses things like .ToListAsync() and a front end in C#, so I'd rather just not deal with converting from Task to Async then back again.
I would suggest implementing your solution in terms of the interfaces behind the concept of awaitable in the TPL, namely INotifyCompletion and ICriticalNotifyCompletion. Also, to implement map correctly, you should really do it in terms of bind. This is something that there are already some existing solutions for in F#, such as the TaskBuilder library. Personally, I have been using the following in a library for years without any issues:
open System.Runtime.CompilerServices
open System.Threading.Tasks
type TaskStep<'result> =
| Value of 'result
| AsyncValue of 'result Task
| Continuation of ICriticalNotifyCompletion * (unit -> 'result TaskStep)
and StateMachine<'a>(firstStep) as this =
let methodBuilder = AsyncTaskMethodBuilder<'a Task>()
let mutable continuation = fun () -> firstStep
let nextAwaitable() =
try
match continuation() with
| Value r ->
methodBuilder.SetResult(Task.FromResult(r))
null
| AsyncValue t ->
methodBuilder.SetResult(t)
null
| Continuation (await, next) ->
continuation <- next
await
with
| exn ->
methodBuilder.SetException(exn)
null
let mutable self = this
member __.Run() =
methodBuilder.Start(&self)
methodBuilder.Task
interface IAsyncStateMachine with
member __.MoveNext() =
let mutable await = nextAwaitable()
if not (isNull await) then
methodBuilder.AwaitUnsafeOnCompleted(&await, &self)
member __.SetStateMachine(_) =
()
type Binder<'out> =
static member inline GenericAwait< ^abl, ^awt, ^inp
when ^abl : (member GetAwaiter : unit -> ^awt)
and ^awt :> ICriticalNotifyCompletion
and ^awt : (member get_IsCompleted : unit -> bool)
and ^awt : (member GetResult : unit -> ^inp) >
(abl : ^abl, continuation : ^inp -> 'out TaskStep) : 'out TaskStep =
let awt = (^abl : (member GetAwaiter : unit -> ^awt)(abl))
if (^awt : (member get_IsCompleted : unit -> bool)(awt))
then continuation (^awt : (member GetResult : unit -> ^inp)(awt))
else Continuation (awt, fun () -> continuation (^awt : (member GetResult : unit -> ^inp)(awt)))
module TaskStep =
let inline bind f step : TaskStep<'a> =
Binder<'a>.GenericAwait(step, f)
let inline toTask (step: TaskStep<'a>) =
try
match step with
| Value x -> Task.FromResult(x)
| AsyncValue t -> t
| Continuation _ as step -> StateMachine<'a>(step).Run().Unwrap()
with
| exn ->
let src = new TaskCompletionSource<_>()
src.SetException(exn)
src.Task
module Task =
let inline bind f task : Task<'a> =
TaskStep.bind f task |> TaskStep.toTask
let inline map f task : Task<'b> =
bind (f >> Value) task
FsToolkit.ErrorHandling implements it here. I'll paste the current version below as it's quite short. It uses the TaskBuilder library Aaron mentioned.
module Task =
let singleton value = value |> Task.FromResult
let bind (f : 'a -> Task<'b>) (x : Task<'a>) = task {
let! x = x
return! f x
}
let map f x = x |> bind (f >> singleton)
Additionally, FSharpPlus has an independent implementation of Task.map here.
Throwing the exception again in the continuation would make for an incorrect stack trace.
It's a mapping from 'A -> 'B, so it's probably best to lay it out explicitly.
let rec map (continuation: 'A -> 'B) (t: Task<'A>) =
let rec map_resolved (task: Task<'A>) =
match task.Status with
| TaskStatus.RanToCompletion -> Task.FromResult(continuation task.Result)
| TaskStatus.Faulted -> Task.FromException<'B>(task.Exception)
| TaskStatus.Canceled -> Task.FromCanceled<'B>(CancellationToken.None)
| _ -> task.ContinueWith(map_resolved).Unwrap()
map_resolved t
Can you explain why one works but not the other?
Given
//fu : unit -> unit
let fu() = ();;
This works
//exec : (unit -> unit) -> int -> unit
let exec (f:(unit -> unit)) (data:int) = f();;
//this works, and p : int -> unit
let p = exec fu;;
And it works for other types of data such as string, long, etc.
This doesn't work
//exec : (unit -> unit) -> obj -> unit
let exec (f:(unit -> unit)) (data:obj) = f();;
let p = exec fu;;
and I get the following error:
error FS0030: Value restriction. The value 'p' has been inferred to have generic type
val p : ('_a -> unit)
Either make the arguments to 'p' explicit or, if you do not intend for it to be generic, add a type annotation.
Notice the only difference between these cases is the type of the data parameter.
When it is obj or System.Object or 'a - it doesn't work.
Another thing is that if data has type obj then the following happens:
//Data type is obj
let exec (f:(unit -> unit)) (data:obj) = f();;
//specifying parameters explicitly
let p x = exec fu x;;
Now p has the signature of 'a -> unit, not obj -> unit.
So the question is: why the "shortcuted" currying doesn't work when data is obj or 'a and why the type of p is 'a -> unit when data was obj?
So I think the problem is that F# appears to be generalizing at the wrong point (from your point of view):
Here is a version of your code that at first glance shouldn't typecheck:
let exec (f:unit -> unit) (data:obj) = f();;
let p:int -> unit = exec (fun () -> ());;
This seems weird as int <> obj.
Also, here is an even simpler example which shows your behaviour (from the spec with modifications)
type Base() =
member b.X = 1
type Derived(i : int) =
inherit Base()
member d.Y = i
let exec (f:unit -> unit) (data:Base) = f();;
let p = exec (fun () -> ());;
which produces a value restriction error.
This makes it more clear that as F# inserts an implicit upcast before the function calls, the code is valid where it is a function, but once you make it an explicit value, this cast can't be used.
If you want your code to compile, you need to move the location of the upcast by adding a type annotation:
let exec (f:unit -> unit) (data:obj) = f()
let p:obj -> unit = exec (fun () -> ());;
I have the following code snippet using the reactive extensions:
let value : 't = ...
Observable.Create<'t>(fun observer ->
let subject = new BehaviorSubject<'t>(value)
let d0 = subject.Subscribe(observer)
let d1 = observable.Subscribe(subject)
new CompositeDisposable(d0, d1) :> IDisposable
)
This works. However if I drop the upcast to IDisposable then the code fails
to compile, citing ambiguous overloads. However CompositeDisposable is an
IDisposable. Why is the type inference engine failing to resolve this? Note I use this pattern almost all the time in C# returning CompositeDisposable from Observable.Create without having to upcast.
As #kvb said, functions don't support variance so upcast is required for interfaces and subclasses.
Here is a small example demonstrating the behavior with subclasses:
type A() =
member x.A = "A"
type B() =
inherit A()
member x.B = "B"
let f (g: _ -> A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // fails
If function f is written by you, adding type constraints could help:
// This works for interface as well
let f (g: _ -> #A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // works
Otherwise, you have to do a litle upcast as your example described.
EDIT: Since F# 6.0, auto-upcasting of interfaces and subclasses is now supported by default.
I want to write a function in F#, that exposes the following type signature to C#:
public static FSharpFunc<FSharpFunc<Unit,Unit>,Unit> foo(Action<Action> f)
In F# I tried writing:
let foo (f : Action<Action>) : ((unit -> unit) -> unit) = ...
But that produces the C# signature:
public static void foo(Action<Action> f, FSharpFunc<Unit,Unit> x)
The F# has treated my code equivalently to:
let foo (f : Action<Action>) (g : unit -> unit) : unit = ...
Of course, these are equivalent to F#, but very different in C#. Is there anything I can do to produce the C# I want? (F# 2.0.0.0)
As a quick hack, I rewrote my F# to:
let foo (f : Action<Action>) ((unit -> unit) -> unit)[] = ...
Then I just use Head in the C#.
If you write let foo x = fun () -> ... then the F# compiler optimizes the code and compiles it as a method that takes two arguments (instead of a method returning function which is what you need). To get a function value as the result, you need to "do something" before returning the function:
// Will be compiled as method taking Action, FastFunc and returning void
let foo1(x : Action<Action>) : (unit -> unit) -> unit =
fun f -> f ()
// Will be compiled as method taking Action and returning FastFunc of FastFunc
let foo2(x : Action<Action>) : ((unit -> unit) -> unit) =
ignore ();
fun f -> f ()
That said, exposing F# function type to C# in any way is a bad pattern and it shouldn't be done. When you have some F# API that is supposed to be used from C#, you should expose functions as delegates, so that C# consumers can use them naturally (without converting Action to F# function explicitly). It is generally easier to write the wrapping on the F# side.
Either:
Add a signature file, with val foo : Action<Action> -> ((unit -> unit) -> unit).
Use a static member of a nominal type, rather than a let-bound value in a module. That is, static member foo (x:Action<Action>) : ((unit -> unit) -> unit) = ...
something like this?
open System
let foo(x : Action<Action>) : (unit -> unit) -> unit = failwith "..."
I'm wondering what others have come up with for dealing with Nullable<'T> in F#. I want to use Nullable<'T> on data types so that serialization works properly (i.e., doesn't write out F# option type to XML). But, I don't want my code stuck dealing with the ugliness of dealing with Nullable<'T> directly. Any suggestions?
Is it better to use active patterns to match directly on Nullable, or just a converter to option and use Some/None matching?
Additionally, I'd love to hear ideas on dealing with nullable references in a nice manner too. If I use, say "string option", then I end up with the F# option type wrapping things. If I don't then I can't distinguish between truly optional strings and strings that shouldn't be null.
Any chance .NET 4 will take on an Option<'T> to help out? (If it's part of the BCL, then we might see better support for it...)
As active patterns as options plays nicely with pattern matching, but is seems by using active patterns (i.e. typeof and ??) your code will eat more ticks.
The base question is how you will deal with your nullable references?
In case your code is long chained computations it's nice to use monadic syntax:
type Maybe<'a> = (unit -> 'a option)
let succeed x : Maybe<'a> = fun () -> Some(x)
let fail : Maybe<'a> = fun () -> None
let run (a: Maybe<'a>) = a()
let bind p rest = match run p with None -> fail | Some r -> (rest r)
let delay f = fun () -> run (f ())
type MaybeBuilder() =
member this.Return(x) = succeed x
member this.Let(p,rest) = rest p
member this.Bind(p,rest) = bind p rest
member this.Delay(f) = delay f
let maybe = new MaybeBuilder()
let add (a:'a) (b:'a) =
maybe {
match TryGetNumericAssociation<'a>() with
| Some v -> return (v.Add(a,b))
| _ -> return! fail
}
let add3 (a:'a) (b:'a) (c:'a) =
maybe {
let! ab = add a b
let! abc = add ab c
return abc
}
> let r1 = add 1 2;;
val r1 : (unit -> int option)
> r1();;
val it : int option = Some 3
> let r2 = add "1" "2";;
val r2 : (unit -> string option)
> r2();;
val it : string option = None
> let r3 = add3 "one" "two" "three";;
val r3 : (unit -> string option)
> r3();;
val it : string option = None