I'm struggling somewhat to translate a piece of C# code that defines a static, generic extension, recursive extension method to F#. The particular piece of code is Daniel Smith's Stackoverflow Community Wiki piece at Write an Rx "RetryAfter" extension method. It's defined like so
public static IObservable<TSource> RetryAfterDelay<TSource, TException>(
this IObservable<TSource> source,
TimeSpan retryDelay,
int retryCount,
IScheduler scheduler) where TException : Exception
{
return source.Catch<TSource, TException>(ex =>
{
if (retryCount <= 0)
{
return Observable.Throw<TSource>(ex);
}
return
source.DelaySubscription(retryDelay, scheduler)
.RetryAfterDelay<TSource, TException>(
retryDelay, --retryCount, scheduler);
});
}
I'm unable to come up with a way to define the function so that I could call it inside the function. A current, simplified version I have is like so, wherein the compiler tells The field, constructor or member 'retryAfterDelay' is not defined
open System
open FSharp.Reactive
open System.Reactive
open System.Reactive.Concurrency
open System.Reactive.Linq
open System.Reactive.Threading.Tasks
open System.Runtime.CompilerServices
//Note that to declare .NET compatible extensions methods "correctly" in F#, one
//needs to also add the assembly level extension attribute. There's a good summary
//by Lincoln Atkinson at http://latkin.org/blog/2014/04/30/f-extension-methods-in-roslyn/.
[<assembly:Extension>]
do ()
[<Extension>]
type ObservableExtensions =
[<Extension>]
static member inline retryAfterDelay((source: IObservable<_>), (retryDelay: TimeSpan), retryCount, (scheduler: IScheduler)): IObservable<_> =
source.Catch(fun ex -> source.DelaySubscription(retryDelay, scheduler).retryAfterDelay(retryDelay, retryCount - 1, scheduler))
[<EntryPoint>]
let main argv =
0
Should this be possible? I've tried to come up with an example of this particular case, but thus far in vain.
<edit: Now a whole program included. Nugets are Install-Package Rx-Main and Install-Package FSharp.Reactive, compiled with VS 2013, .NET 4.5.1 and FSharp.Core 4.3.1.0 in Debug mode.
<edit 2: There's a tangential note regarding the keyword rec in recursive member functions at Record-type recursive member functions and the “rec” keyword. In short, it's concluded the rec binding in recursive member functions is incorrect and thus compiler flags it as an error.
<edit 3: Maybe a potential way to achieve this is as follows. I haven't yet checked if this actually works, it may take some time so I'll just add this here an intermediary note...
[<Extension>]
type ObservableExtensions =
[<Extension>]
static member inline retryAfterDelay((source: IObservable<_>), (retryDelay: TimeSpan), retryCount, (scheduler: IScheduler)): IObservable<_> =
ObservableExtensions.retryAfterDelay(source.DelaySubscription(retryDelay, scheduler), retryDelay, retryCount - 1, scheduler)
<edit 4:
Taking cues from elsewhere and Gustavo's answer and to honor the original piece of code with the type constraints, I came up with the following
//Note that to declare .NET compatible extensions methods "correctly" in F#, one
//needs to also add the assembly level extension attribute. There's a good summary
//by Lincoln Atkinson at http://latkin.org/blog/2014/04/30/f-extension-methods-in-roslyn/.
[<assembly:Extension>]
do ()
[<Extension>]
type ObservableExtensions =
[<Extension>]
[<CompiledName("PascalCase")>]
static member inline retryAfterDelay<'TSource, 'TException when 'TException :> System.Exception>(source: IObservable<'TSource>, retryDelay: int -> TimeSpan, maxRetries, scheduler: IScheduler): IObservable<'TSource> =
let rec go(source: IObservable<'TSource>, retryDelay: int -> TimeSpan, retries, maxRetries, scheduler: IScheduler): IObservable<'TSource> =
source.Catch<'TSource, 'TException>(fun ex ->
if maxRetries <= 0 then
Observable.Throw<'TSource>(ex)
else
go(source.DelaySubscription(retryDelay(retries), scheduler), retryDelay, retries + 1, maxRetries - 1, scheduler))
go(source, retryDelay, 1, maxRetries, scheduler)
A few notes
I'm uncertain if 'TSource makes any difference or would the wildcard _ as used in previous versions be just as good. Nevertheless, I believe this represents the original code.
I modified the interface to include a factory function to create a delay. The function could be, for instance, be let dummyRetryStrategy(retryCount: int) = TimeSpan.FromSeconds(1.0) and an example use case would be let a = Seq.empty<int>.ToObservable().retryAfterDelay(dummyRetryStrategy, 3, Scheduler.Default).
The interface could be polished at least regarding the scheduler, and this is code is essentially untested. Hmm, maybe this should be linked back to the community wiki answer.
Would the interface be a usable one from other .NET languages such as C# and VB.NET. I have actually a post pending on a code very related to this at Code Review SO, so maybe it's best handled there (I'll update it tomorrow, in about twenty hours or so).
You can use it as an extension method once you finish the Type declaration. So you can write the method like this:
[<Extension>]
type ObservableExtensions =
[<Extension>]
static member retryAfterDelay(source: IObservable<_>, retryDelay: TimeSpan, retryCount, scheduler: IScheduler): IObservable<_> =
ObservableExtensions.retryAfterDelay(source.Catch(fun ex -> source.DelaySubscription(retryDelay, scheduler)),retryDelay, retryCount - 1, scheduler)
After that you can immediately use it. If you need it in another extension from the same class you can use it by re-opening again the Type declaration:
type ObservableExtensions with
[<Extension>]
static member anotherExtension (x: IObservable<_>) = x.retryAfterDelay // now you can use it as an extension method
The alternative is using let and rec inside an internal function:
[<Extension>]
static member retryAfterDelay(source: IObservable<_>, retryDelay: TimeSpan, retryCount, scheduler: IScheduler): IObservable<_> =
let rec go (source: IObservable<_>, retryDelay: TimeSpan, retryCount, scheduler: IScheduler): IObservable<_> =
go (source.Catch(fun ex -> source.DelaySubscription(retryDelay, scheduler)),retryDelay, retryCount - 1, scheduler)
go (source, retryDelay, retryCount, scheduler)
Which I prefer for F# since the recursion is explicit in the code.
Related
This code snippet reproduces a problem I am having with some production code. The function containsProperty represents a real world function that is actually in a library, so that I have no say in what the signature is.
The problem is that I can't figure out how to create a wrapper function that can take a normal function as argument, and then pass that on to containsProperty. I can call containsProperty directly with a function as a lambda expression, but I can't call it with a function that comes from some other source.
The function addToGroup is the best I've come up with so far, and it uses quotations. There are two problems with that approach, which I am trying to figure out. First, how do I get rid of the Func cast in the quotation? Perhaps somehow move it into addToGroup? Second, can I build on this in order to just pass a function? I haven't succeeded in finding something that doesn't produce either a compile time error or a runtime error.
The function addToGroup2 is what I'd like to do, but it doesn't compile. The error message is "No constructors are available for the type 'Quotations.Expr<'a>'".
Why do I bother to struggle with this? Because as long as I can't treat the passed in function as a first class value, I can't create the design I'm after. I want these functions to come along from a collection of records.
If you paste this snippet into LINQPad or something, comment out addToGroup2 and the calls to it, in order to make the snippet compile and run.
open System
open System.ComponentModel
open System.ComponentModel.DataAnnotations // Reference to this assembly required.
type CfgSettings = {
mutable ConnectionString: string
mutable Port: int
}
and CfgSettingsMetadata() =
static member containsProperty<'TProperty>(propertyExpression: Linq.Expressions.Expression<Func<CfgSettings,'TProperty>>) =
Console.WriteLine "good!"
static member addToGroup f =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
static member addToGroup2 (f: CfgSettings -> 'TProperty) =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression (Quotations.Expr<Func<CfgSettings,'TProperty>>f)) |> ignore
static member BuildMetadata () =
CfgSettingsMetadata.containsProperty(fun x -> x.ConnectionString)
CfgSettingsMetadata.containsProperty(fun x -> x.Port)
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.ConnectionString) #>
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.Port) #>
CfgSettingsMetadata.addToGroup2 (fun x -> x.ConnectionString)
CfgSettingsMetadata.addToGroup2 (fun x -> x.Port)
CfgSettingsMetadata.BuildMetadata()
Both answers in question Expression<Func<T, bool>> from a F# func helped me somewhat, but I haven't found a solution yet.
So, there are two questions here.
How to pass a function without having to wrap it in <# ... #>?
For this, you just need to add the [<ReflectedDefinition>] attribute to your method's parameter. It implicitly wraps the argument passed to it in a quotation.
type CfgSettingsMetadata() =
static member addToGroup([<ReflectedDefinition>] f: Expr<CfgSettings -> 'TProperty>) =
CfgSettingsMetadata.containsProperty(LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(Func<_, _>(fun x -> x.ConnectionString))
How to convert from Expr<a -> b> to Expression<Func<a, b>>?
This is indeed explained in the question you linked, although the API has changed a bit since then.
type CfgSettingsMetadata() =
static member addToGroup ([<ReflectedDefinition>] (f: Expr<CfgSettings -> 'TProperty>)) =
let call = LeafExpressionConverter.QuotationToExpression f :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
let e = Expression.Lambda<Func<CfgSettings, 'TProperty>>(lambda.Body, lambda.Parameters)
CfgSettingsMetadata.containsProperty(e) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(fun x -> x.ConnectionString)
So, I was trying to get this simple test working in an F# console app:
open System.Reflection
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
[<Export(typeof<int -> string>)>]
let toString(i: int) = i.ToString()
[<EntryPoint>]
let main argv =
use catalog = new AssemblyCatalog(Assembly.GetEntryAssembly())
use container = new CompositionContainer(catalog)
let myFunction = container.GetExportedValue<int -> string>()
let result = myFunction(5)
0
I expected MEF to get the function properly resolved, but it doesn't.
Instead, I get this:
An unhandled exception of type
'System.ComponentModel.Composition.CompositionContractMismatchException'
occurred in System.ComponentModel.Composition.dll
Additional information:
Cannot cast the underlying exported value of type 'Program.toString (ContractName="Microsoft.FSharp.Core.FSharpFunc(System.Int32,System.String)")' to type 'Microsoft.FSharp.Core.FSharpFunc``2[System.Int32,System.String]'.
What am I missing here?
What is the difference between FSharpFunc(System.Int32, System.String) and FSharpFunc``2[System.Int32, System.String]?
What is the correct way to import/export F# functions via MEF?
The compiler turns top-level F# functions into methods, so your example will be compiled as:
[Export(FSharpFunc<int,string>)]
public string toString(int i) { return i.ToString(); }
This is probably causing the error. You can force the compiler to produce a property getter of FSharpFunc type by calling some operation that returns a function - even a simple identity function will don:
let makeFunc f = f
[<Export(typeof<int -> string>)>]
let toString = makeFunc <| fun (i:int) ->
i.ToString()
I have not tested this, but I think it could work. That said, it is probably safer to go with a simple single-method interface in this case.
I hit something new to me with the following piece of code when following the equivalent in C# here. The compiler gives multiple errors basically telling the IConnectableObservable created in source.Publish() does not match IObservable even though it derives from it (according to the MSDN article linked).
Is there something in F# that is different with regard to C# concerning inheritance in this case or can someone provider pointers as to what is going on? Have I just made a typo I can't see? What comes to the heading regarding covariance, it's just a wild guess as I'm at least temporarily out of ideas. And so, maybe writing somewhere may help me and others...
One example of the many error messages:
No overloads match for method 'Create'. The available overloads are shown below (or in the Error List window).
No overloads match for method 'Switch'. The available overloads are shown below (or in the Error List window).
Error Possible overload: '(extension) IObservable.Switch<'TSource>() :
IObservable<'TSource>'. Type constraint mismatch. The type
IObservable<IConnectableObservable<'b>> is not compatible with type
IObservable<IObservable<'a>> The type 'IObservable<'a>' does not match the type 'IConnectableObservable<'b>'.
open System.Reactive.Concurrency
open System.Reactive.Disposables
open System.Reactive.Subjects
open System.Reactive.Linq
type Observable with
static member inline Suspendable(source: IObservable<_>, suspend: IObservable<bool>, isSuspendedInitially: bool): IObservable<_> =
Observable.Create<_>(fun observer ->
let shared = source.Publish()
let pausable =
suspend.StartWith(isSuspendedInitially)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(fun p -> if p then shared else Observable.Empty<_>())
.Switch()
new CompositeDisposable(pausable.Subscribe(observer), shared.Connect()))
The corresponding C# code
public static class RxExtensions
{
public static IObservable<T> Suspendable<T>(this IObservable<T> stream, IObservable<bool> suspend, bool isSuspendedInitially)
{
return Observable.Create<T>(o =>
{
var shared = stream.Publish();
var pausable = suspend
.StartWith(isSuspendedInitially)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(p => p ? shared : Observable.Empty<T>())
.Switch();
return new CompositeDisposable(pausable.Subscribe(o), shared.Connect());
});
}
}
This was a bit tricky, but you need to add two upcasts: shared to IObservable<_>, and the result of the lambda function to IDisposable. These would be implicit in C#, but need to be explicit in F#:
type Observable with
static member inline Suspendable (source: IObservable<_>,
suspend: IObservable<bool>,
isSuspendedInitially: bool): IObservable<'a> =
Observable.Create<_>(fun observer ->
let shared = source.Publish()
let pausable =
suspend.StartWith(isSuspendedInitially)
.TakeUntil(shared.LastOrDefaultAsync())
.DistinctUntilChanged()
.Select(fun p -> if p then shared :> IObservable<_>
else Observable.Empty<_>())
.Switch()
new CompositeDisposable(pausable.Subscribe(observer),
shared.Connect()) :> IDisposable)
After a while again I was leafing through some Rx code here in SO and came across to a question How to implement polling using Observables?.
Intriquing from the F# perspective is the use of (self-defined) Either type, or Choice in F# parlor. Alas, I get the translation wrong on many levels, beginning already from the types.
But rather than just quit attempting to translate, perhaps this could be of use as a broader education tool. Could someone lend a functioning F# brain and help translate the following piece(s) of C# code?
I have used F# TaskBuilder, but noticed just recently that it doesn't implemented the TryWith part of a computation builder in TaskBuilder. So, it may become difficult to translate the first piece of C# code (or perhaps one should go the async route), there's another version provided in the source SO link that doesn't use an asynchornous structure. Luck regarding this question, or unluck, I'm not able to translate that either.
The erros I get are of the sort:
Type mismatch. Expecting a IScheduler -> CancellationToken -> Task but given a 'a * CancellationToken -> 'b The type 'IScheduler' does not match the type ''a * CancellationToken'
Type mismatch. Expecting a IObservable<Choice<'TResult,exn>> but given a
IObservable<'TResult> The resulting type would be infinite when unifying ''TResult' and 'Choice<'TResult,exn>'
and so forth.
Install-Package FSharpx
Install-Package Rx-Main
-
[<Extension>]
type ObservableExtensions() =
static member inline poll<'TResult, 'TArg>(asyncFunction: 'TArg -> IObservable<'TResult>, parameterFactory: 'TArg, interval:TimeSpan, scheduler: IScheduler): IObservable<Choice<'TResult, exn>> =
Observable.Create<'TResult>(fun(observer:IObserver<'TResult>) ->
let task = new TaskBuilder()
let t(ctrl:IScheduler, ct:CancellationToken) = task {
while not <| ct.IsCancellationRequested do
try
let! result = asyncFunction(parameterFactory)
observer.OnNext(Choice1Of2(result))
with ex ->
observer.OnNext(Choice2Of2(ex))
do! ctrl.Sleep(interval, ct)
}
scheduler.ScheduleAsync(Func<IScheduler, CancellationToken, Task>(t)))
And the corresponding C# code (1):
public IObservable<Either<Exception, TResult>> Poll<TResult, TArg>(
Func<TArg, IObservable<TResult>> asyncFunction,
Func<TArg> parameterFactory,
TimeSpan interval,
IScheduler scheduler)
{
return Observable.Create<Either<Exception, TResult>>(observer =>
{
return scheduler.ScheduleAsync(async (ctrl, ct) => {
while(!ct.IsCancellationRequested)
{
try
{
var result = await asyncFunction(parameterFactory());
observer.OnNext(Either.Right<Exception,TResult>(result));
}
catch(Exception ex)
{
observer.OnNext(Either.Left<Exception, TResult>(ex));
}
await ctrl.Sleep(interval, ct);
}
});
});
}
Alternative C# code
public IObservable<Either<Exception, TResult>> Poll2<TResult, TArg>(
Func<TArg, IObservable<TResult>> asyncFunction,
Func<TArg> parameterFactory,
TimeSpan interval,
IScheduler scheduler)
{
return Observable.Create<Either<Exception, TResult>>(
observer =>
Observable.Defer(() => asyncFunction(parameterFactory()))
.Select(Either.Right<Exception, TResult>)
.Catch<Either<Exception, TResult>, Exception>(
ex => Observable.Return(Either.Left<Exception, TResult>(ex)))
.Concat(Observable.Defer(
() => Observable.Empty<Either<Exception, TResult>>()
.Delay(interval, scheduler)))
.Repeat().Subscribe(observer));
}
Just a note that this bears some similarity to How to write a generic, recursive extension method in F#? and consequently to Write an Rx “RetryAfter” extension method extension method
<edit: To complement theexcellent answer of MisterMetaphor, I'll add a version without interval here too.
type Observable with
static member Poll2(f: unit -> IObservable<_>, interval: TimeSpan, sched: IScheduler) : IObservable<_> =
Observable.Create<_>(fun observer ->
Observable.Defer(f)
.Select(Choice1Of2)
.Catch(Choice2Of2 >> Observable.Return)
.Concat(Observable.Defer(fun _ -> Observable.Empty().Delay(interval, sched)))
.Repeat()
.Subscribe(observer))
static member Poll2(f: 'a -> IObservable<_>, argFactory: unit -> 'a, interval: TimeSpan, sched: IScheduler) =
Observable.Poll2(argFactory >> f, interval, sched)
I'm not sure if this is needed, but a due note on a subtle bug on .Subscribein F# (at least of Visual F# 3.1.1.0) as discovered in SO here, more here).
If you don't absolutely have to use Observable.Create, you can achieve similar results with Observable.Interval:
type Observable with
static member Poll(f : unit -> IObservable<_>, interval : TimeSpan, sched : IScheduler) : IObservable<_> =
Observable.Interval(interval, sched)
.SelectMany(fun _ ->
Observable.Defer(f)
.Select(Choice1Of2)
.Catch(Choice2Of2 >> Observable.Return))
// An overload that matches your original function
static member Poll(f : 'a -> IObservable<_>, argFactory : unit -> 'a, interval : TimeSpan, sched : IScheduler) =
Observable.Poll(argFactory >> f, interval, sched)
What I like about this implementation is that you don't have to go down to the level of directly using schedulers and Observable.Create. I think you should always use existing combinators/operators unless you absolutely have to do otherwise.
Also, Observable.Interval uses SchedulePeriodic (evident here) which is probably more efficient and correct than your Task-based implementation.
I know virtually nothing about F#. I don’t even know the syntax, so I can’t give examples.
It was mentioned in a comment thread that F# can declare functions that can take parameters of multiple possible types, for example a string or an integer. This would be similar to method overloads in C#:
public void Method(string str) { /* ... */ }
public void Method(int integer) { /* ... */ }
However, in CIL you cannot declare a delegate of this form. Each delegate must have a single, specific list of parameter types. Since functions in F# are first-class citizens, however, it would seem that you should be able to pass such a function around, and the only way to compile that into CIL is to use delegates.
So how does F# compile this into CIL?
This question is a little ambiguous, so I'll just ramble about what's true of F#.
In F#, methods can be overloaded, just like C#. Methods are always accessed by a qualified name of the form someObj.MethodName or someType.MethodName. There must be context which can statically resolve the overload at compile-time, just as in C#. Examples:
type T() =
member this.M(x:int) = ()
member this.M(x:string) = ()
let t = new T()
// these are all ok, just like C#
t.M(3)
t.M("foo")
let f : int -> unit = t.M
let g : string-> unit = t.M
// this fails, just like C#
let h = t.M // A unique overload for method 'M' could not be determined
// based on type information prior to this program point.
In F#, let-bound function values cannot be overloaded. So:
let foo(x:int) = ()
let foo(x:string) = () // Duplicate definition of value 'foo'
This means you can never have an "unqualified" identifier foo that has overloaded meaning. Each such name has a single unambiguous type.
Finally, the crazy case which is probably the one that prompts the question. F# can define inline functions which have "static member constraints" which can be bound to e.g. "all types T that have a member property named Bar" or whatnot. This kind of genericity cannot be encoded into CIL. Which is why the functions that leverage this feature must be inline, so that at each call site, the code specific-to-the-type-used-at-that-callsite is generated inline.
let inline crazy(x) = x.Qux(3) // elided: type syntax to constrain x to
// require a Qux member that can take an int
// suppose unrelated types U and V have such a Qux method
let u = new U()
crazy(u) // is expanded here into "u.Qux(3)" and then compiled
let v = new V()
crazy(v) // is expanded here into "v.Qux(3)" and then compiled
So this stuff is all handled by the compiler, and by the time we need to generate code, once again, we've statically resolved which specific type we're using at this callsite. The "type" of crazy is not a type that can be expressed in CIL, the F# type system just checks each callsite to ensure the necessary conditions are met and inlines the code into that callsite, a lot like how C++ templates work.
(The main purpose/justification for the crazy stuff is for overloaded math operators. Without the inline feature, the + operator, for instance, being a let-bound function type, could either "only work on ints" or "only work on floats" or whatnot. Some ML flavors (F# is a relative of OCaml) do exactly that, where e.g. the + operator only works on ints, and a separate operator, usually named +., works on floats. Whereas in F#, + is an inline function defined in the F# library that works on any type with a + operator member or any of the primitive numeric types. Inlining can also have some potential run-time performance benefits, which is also appealing for some math-y/computational domains.)
When you're writing C# and you need a function that can take multiple different parameter sets, you just create method overloads:
string f(int x)
{
return "int " + x;
}
string f(string x)
{
return "string " + x;
}
void callF()
{
Console.WriteLine(f(12));
Console.WriteLine(f("12"));
}
// there's no way to write a function like this:
void call(Func<int|string, string> func)
{
Console.WriteLine(func(12));
Console.WriteLine(func("12"));
}
The callF function is trivial, but my made-up syntax for the call function doesn't work.
When you're writing F# and you need a function that can take multiple different parameter sets, you create a discriminated union that can contain all the different parameter sets and you make a single function that takes that union:
type Either = Int of int
| String of string
let f = function Int x -> "int " + string x
| String x -> "string " + x
let callF =
printfn "%s" (f (Int 12))
printfn "%s" (f (String "12"))
let call func =
printfn "%s" (func (Int 12))
printfn "%s" (func (String "12"))
Being a single function, f can be used like any other value, so in F# we can write callF and call f, and both do the same thing.
So how does F# implement the Either type I created above? Essentially like this:
public abstract class Either
{
public class Int : Test.Either
{
internal readonly int item;
internal Int(int item);
public int Item { get; }
}
public class String : Test.Either
{
internal readonly string item;
internal String(string item);
public string Item { get; }
}
}
The signature of the call function is:
public static void call(FSharpFunc<Either, string> f);
And f looks something like this:
public static string f(Either _arg1)
{
if (_arg1 is Either.Int)
return "int " + ((Either.Int)_arg1).Item;
return "string " + ((Either.String)_arg1).Item;
}
Of course you could implement the same Either type in C# (duh!), but it's not idiomatic, which is why it wasn't the obvious answer to the previous question.
Assuming I understand the question, in F# you can define expressions which depend on the availability of members with particular signatures. For instance
let inline f x a = (^t : (member Method : ^a -> unit)(x,a))
This defines a function f which takes a value x of type ^t and a value a of type ^a where ^t has a method Method taking an ^a to unit (void in C#), and which calls that method. Because this function is defined as inline, the definition is inlined at the point of use, which is the only reason that it can be given such a type. Thus, although you can pass f as a first class function, you can only do so when the types ^t and ^a are statically known so that the method call can be statically resolved and inserted in place (and this is why the type parameters have the funny ^ sigil instead of the normal ' sigil).
Here's an example of passing f as a first-class function:
type T() =
member x.Method(i) = printfn "Method called with int: %i" i
List.iter (f (new T())) [1; 2; 3]
This runs the method Method against the three values in the list. Because f is inlined, this is basically equivalent to
List.iter ((fun (x:T) a -> x.Method(a)) (new T())) [1; 2; 3]
EDIT
Given the context that seems to have led to this question (C# - How can I “overload” a delegate?), I appear not to have addressed your real question at all. Instead, what Gabe appears to be talking about is the ease with which one can define and use discriminated unions. So the question posed on that other thread might be answered like this using F#:
type FunctionType =
| NoArgument of (unit -> unit)
| ArrayArgument of (obj[] -> unit)
let doNothing (arr:obj[]) = ()
let doSomething () = printfn "'doSomething' was called"
let mutable someFunction = ArrayArgument doNothing
someFunction <- NoArgument doSomething
//now call someFunction, regardless of what type of argument it's supposed to take
match someFunction with
| NoArgument f -> f()
| ArrayArgument f -> f [| |] // pass in empty array
At a low level, there's no CIL magic going on here; it's just that NoArgument and ArrayArgument are subclasses of FunctionType which are easy to construct and to deconstruct via pattern matching. The branches of the pattern matching expression are morally equivalent to a type test followed by property accesses, but the compiler makes sure that the cases have 100% coverage and don't overlap. You could encode the exact same operations in C# without any problem, but it would be much more verbose and the compiler wouldn't help you out with exhaustiveness checking, etc.
Also, there is nothing here which is particular to functions; F# discriminated unions make it easy to define types which have a fixed number of named alternatives, each one of which can have data of whatever type you'd like.
I'm not quite sure that understand your question correctly... F# compiler uses FSharpFunc type to represent functions. Usually in F# code you don't deal with this type directly, using fancy syntactic representation instead, but if you expose any members that returns or accepts function and use them from another language, line C# - you will see it.
So instead of using delegates - F# utilizes its special type with concrete or generic parameters.
If your question was about things like add something-i-don't-know-what-exactly-but-it-has-addition-operator then you need to use inline keyword and compiler will emit function body in the call site. #kvb's answer was describing exactly this case.