Related
In Kotlin I can do something like:
var myType : KClass<String>? = null
and can assign to it like:
myType = String::class
but NOT like:
myType = Int::class // Type mismatch: inferred type in KClass<Int> but KClass<String>? was expected
Is there something similar in Dart? I know of the Type type but it is not generic and while it can represent String or List<int> I seem not to be able to write similar code as my Kotlin example:
Type? t = null;
I can assign to it:
t = String;
AND also:
t = int;
but I want the second example to fail compilation. I would need some kind of Type<String>. Is this possible in Dart?
The Type class is not generic, and doesn't support subtype checks (or any other reasonable type-related operation). There is no way to use it for what you are trying to do.
So, don't. It's useless anyway. However, in Dart you can create your own type representation that is actually useful, because Dart doesn't erase type arguments, and you can then ask people using your code to ass that instead.
Say:
class MyType<T> implements Comparable<MyType>{ // Or a better name.
const MyType();
Type get type => T;
bool operator >=(MyType other) => other is MyType<T>;
bool operator <=(MyType other) => other >= this;
bool isInstance(Object? object) => object is T;
R runWith<R>(R Function<T>() action) => action<T>();
#override
int get hashCode => T.hashCode;
#override
bool operator==(Object other) => other is MyType && T == other.type;
}
With that you can write:
MyType<String?> type;
type = MyType<Null>(); // valid
type = MyType<String>(); // valid
type = MyType<Never>(); // valid
type = MyType<int>; // EEEK! compile-time error
You can use it where you need to store a type as a value.
The thing is, most of the time you can just use a type variable instead ,and creating an actual value to represent a type is overkill.
So, first try to just use a type parameter, instead of passing around Type or MyType objects. Only if that fails should you consider using MyType. Using Type is probably a mistake since it's not good for anything except doing == checks, which is antithetical to object orientation's idea of subtype subsumption.
I think this is the best you can get :
void main() {
aFunction<String>(String, '');
aFunction<String>(String, 1);
}
void aFunction<V>(Type type, V value) {
print(value.toString());
}
if you run this in a dartpad, you will see that
aFunction<String>(type, 1);
Doesn't compile.
But that's not really efficient because the type isn't guessed by Dart, you have to specify the generic type by hand.
I'm using Dart 2.17
1. There is confliction on Dart Language tour
In Functions section, it says
The => expr syntax is a shorthand for { return expr; }.
Note: Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (;). For example, you can’t put an if statement there, but you can use a conditional expression.
But in the Anonymous functions section, it says
If the function contains only one statement, you can shorten it using arrow notation
Does it mean I can use statement which is not an expression (such as if statement) in anonymous functions?
var fun = () => return 3; // However, this doesn't work.
var gun = () {
return 3; // this works.
}
Or am I confusing concept of expression and statement? I thought
expression : can be evaluated to a value ( 2 + 3 , print('') also falls into an expression )
statement : code that can be executed. all expressions can be statement. if statement and return statement are examples of statement which is not expression.
2. Is this expression or statement
void foo() => true; // this works.
void goo() {
return true; // this doesn't work.
}
void hoo() {
true; // this works.
}
If true is understood as expression, then it will mean return true and I believe it should not work because foo's return type is void.
Then does it mean true in foo is understood as a statement? But this conclusion contradicts with dart language tour. (They are top-level named functions). Also, this means we can use statement with arrow syntax.
I use VSCode and Dart from flutter: 1.22.5. I tell code that works from code that doesn't work based on VSCode error message.
Because this is my first question, I apologize for my short English and ill-formed question.
It must be an expression. The text is misleading.
For the second part, the error you see with
void foo() {
return 0;
}
and not with
void bar() => 0;
is a special case for => in functions returning void. Normally, you can't return a value from a function with return type void, so no return exp;, only return;.
(There are exceptions if exp has type void, null or dynamic, but yours doesn't).
Because people like the short-hand notation of void foo() => anything; so much, you are allowed to do that no matter what the type of anything is. That's why there is a distinction between void foo() { return 0; } and void foo() => 0;. They still mean the same thing, but the type-based error of the former is deliberately suppressed in the latter.
I'm guessing that the author of that section under Anonymous functions was a bit confused. File an issue against it, and get it corrected!
Yeah, even in their example they use a print() function, which they might be confusing as a print "statement", which it clearly is not.
In a c# dll I have a method, that takes func parameters:
public static AttrDiffRule Create<T>(string a_attr, string b_attr, Func<IAttrProxy,IAttrProxy,T,bool> parametricRule, T ruleParam, string desc = null)
and some predefined default methods intended for it:
public static bool NumberEqualsWithTolerance(IAttrProxy a, IAttrProxy b, double tolerance)
Now when using this in C#, I can write the following and it works:
var tmp = DefaultRules.Create("fds", "fds", DefaultRules.NumberEqualsWithTolerance, 10.0);
But, in F# this:
let attrRule = DefaultRules.Create("fd","fdsa", DefaultRules.NumberEqualsWithTolerance, 89.)
gives syntax error: "Error FS0002 This function takes too many arguments, or is used in a context where a function is not expected"
What would be the correct way to pass a C# static method into a parameter expecting a Func<> in F#?
It is important to actually pass in the function, and not a lambda wrapper, because the Create method's job is to use the argument function's MethodInfo, which gets hidden by the lambda wrapper's one.
The passed in function does not have overloads, also tried with specifying the type in place like
(DefaultRules.NumberEqualsWithTolerance : Func<IAttrProxy,IAttrProxy,float,bool>)
This is a case of F# being very thoughtful on your behalf - by helping you write more idiomatic F#.
In .NET, you are not actually passing in the function, as if it's a member reference, rather you are passing in a delegate object of type Func<>. The construction of the delegate object is done implicitly by C# when it has the necessary type information.
We can see this more clearly if we refactor this into an actual delegate type:
public delegate bool ParametricRule<T>(IAttrProxy a, IAttrProxy b, T value);
public static AttrDiffRule Create<T>(string a_attr, string b_attr, ParametricRule<T> parametricRule, T ruleParam, string desc = null)
{
return default;
}
If you try to construct a ParametricRule in F#, you'll see that its type is:
ParametricRule(IAttrProxy -> IAttrProxy -> 'a -> bool)
The rationale is that this way you can use regular F# functions, instead of some un-F#ish tupled input function. And this why it doesn't work in your case.
Because you're trying to throw the tupled version from C# right back at it.
So if you refactor your C# implementation to:
protected static bool NumberEqualsWithToleranceImpl(IAttrProxy a, IAttrProxy b, float tolerance)
{
return default;
}
public static ParametricRule<float> NumberEqualsWithTolerance => NumberEqualsWithToleranceImpl;
you'll see that it works like you'd expect it to, both from F# and C#.
let attrRule = DefaultRules.Create("fd","fdsa", DefaultRules.NumberEqualsWithTolerance, 89.0f) //compiles, yay!
Sometimes the type resolution has trouble when passing a method as a function parameter, because there can be overloads on the method that make the signature ambiguous. You can just wrap the function in a lambda that passes the parameters.
let attrRule =
DefaultRules.Create(
"fd",
"fdsa",
(fun a b tolerance -> DefaultRules.NumberEqualsWithTolerance(a, b, tolerance)),
89.0)
If I have a nullable type Xyz?, I want to reference it or convert it to a non-nullable type Xyz. What is the idiomatic way of doing so in Kotlin?
For example, this code is in error:
val something: Xyz? = createPossiblyNullXyz()
something.foo() // Error: "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Xyz?"
But if I check null first it is allowed, why?
val something: Xyz? = createPossiblyNullXyz()
if (something != null) {
something.foo()
}
How do I change or treat a value as not null without requiring the if check, assuming I know for sure it is truly never null? For example, here I am retrieving a value from a map that I can guarantee exists and the result of get() is not null. But I have an error:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.get("a")
something.toLong() // Error: "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Int?"
The method get() thinks it is possible that the item is missing and returns type Int?. Therefore, what is the best way to force the type of the value to be not nullable?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO. Also to clarify some really old answers written for alphas of Kotlin that are not accurate for current-day Kotlin.
First, you should read all about Null Safety in Kotlin which covers the cases thoroughly.
In Kotlin, you cannot access a nullable value without being sure it is not null (Checking for null in conditions), or asserting that it is surely not null using the !! sure operator, accessing it with a ?. Safe Call, or lastly giving something that is possibly null a default value using the ?: Elvis Operator.
For your 1st case in your question you have options depending on the intent of the code you would use one of these, and all are idiomatic but have different results:
val something: Xyz? = createPossiblyNullXyz()
// access it as non-null asserting that with a sure call
val result1 = something!!.foo()
// access it only if it is not null using safe operator,
// returning null otherwise
val result2 = something?.foo()
// access it only if it is not null using safe operator,
// otherwise a default value using the elvis operator
val result3 = something?.foo() ?: differentValue
// null check it with `if` expression and then use the value,
// similar to result3 but for more complex cases harder to do in one expression
val result4 = if (something != null) {
something.foo()
} else {
...
differentValue
}
// null check it with `if` statement doing a different action
if (something != null) {
something.foo()
} else {
someOtherAction()
}
For the "Why does it work when null checked" read the background information below on smart casts.
For your 2nd case in your question in the question with Map, if you as a developer are sure of the result never being null, use !! sure operator as an assertion:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.get("a")!!
something.toLong() // now valid
or in another case, when the map COULD return a null but you can provide a default value, then Map itself has a getOrElse method:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.getOrElse("z") { 0 } // provide default value in lambda
something.toLong() // now valid
Background Information:
Note: in the examples below I am using explicit types to make the behavior clear. With type inference, normally the types can be omitted for local variables and private members.
More about the !! sure operator
The !! operator asserts that the value is not null or throws an NPE. This should be used in cases where the developer is guaranteeing that the value will never be null. Think of it as an assert followed by a smart cast.
val possibleXyz: Xyz? = ...
// assert it is not null, but if it is throw an exception:
val surelyXyz: Xyz = possibleXyz!!
// same thing but access members after the assertion is made:
possibleXyz!!.foo()
read more: !! Sure Operator
More about null Checking and Smart Casts
If you protect access to a nullable type with a null check, the compiler will smart cast the value within the body of the statement to be non-nullable. There are some complicated flows where this cannot happen, but for common cases works fine.
val possibleXyz: Xyz? = ...
if (possibleXyz != null) {
// allowed to reference members:
possiblyXyz.foo()
// or also assign as non-nullable type:
val surelyXyz: Xyz = possibleXyz
}
Or if you do a is check for a non-nullable type:
if (possibleXyz is Xyz) {
// allowed to reference members:
possiblyXyz.foo()
}
And the same for 'when' expressions that also safe cast:
when (possibleXyz) {
null -> doSomething()
else -> possibleXyz.foo()
}
// or
when (possibleXyz) {
is Xyz -> possibleXyz.foo()
is Alpha -> possibleXyz.dominate()
is Fish -> possibleXyz.swim()
}
Some things do not allow the null check to smart cast for the later use of the variable. The example above uses a local variable that in no way could have mutated in the flow of the application, whether val or var this variable had no opportunity to mutate into a null. But, in other cases where the compiler cannot guarantee the flow analysis, this would be an error:
var nullableInt: Int? = ...
public fun foo() {
if (nullableInt != null) {
// Error: "Smart cast to 'kotlin.Int' is impossible, because 'nullableInt' is a mutable property that could have been changed by this time"
val nonNullableInt: Int = nullableInt
}
}
The lifecycle of the variable nullableInt is not completely visible and may be assigned from other threads, the null check cannot be smart cast into a non-nullable value. See the "Safe Calls" topic below for a workaround.
Another case that cannot be trusted by a smart cast to not mutate is a val property on an object that has a custom getter. In this case, the compiler has no visibility into what mutates the value and therefore you will get an error message:
class MyThing {
val possibleXyz: Xyz?
get() { ... }
}
// now when referencing this class...
val thing = MyThing()
if (thing.possibleXyz != null) {
// error: "Kotlin: Smart cast to 'kotlin.Int' is impossible, because 'p.x' is a property that has open or custom getter"
thing.possiblyXyz.foo()
}
read more: Checking for null in conditions
More about the ?. Safe Call operator
The safe call operator returns null if the value to the left is null, otherwise continues to evaluate the expression to the right.
val possibleXyz: Xyz? = makeMeSomethingButMaybeNullable()
// "answer" will be null if any step of the chain is null
val answer = possibleXyz?.foo()?.goo()?.boo()
Another example where you want to iterate a list but only if not null and not empty, again the safe call operator comes in handy:
val things: List? = makeMeAListOrDont()
things?.forEach {
// this loops only if not null (due to safe call) nor empty (0 items loop 0 times):
}
In one of the examples above we had a case where we did an if check but have the chance another thread mutated the value and therefore no smart cast. We can change this sample to use the safe call operator along with the let function to solve this:
var possibleXyz: Xyz? = 1
public fun foo() {
possibleXyz?.let { value ->
// only called if not null, and the value is captured by the lambda
val surelyXyz: Xyz = value
}
}
read more: Safe Calls
More about the ?: Elvis Operator
The Elvis operator allows you to provide an alternative value when an expression to the left of the operator is null:
val surelyXyz: Xyz = makeXyzOrNull() ?: DefaultXyz()
It has some creative uses as well, for example throw an exception when something is null:
val currentUser = session.user ?: throw Http401Error("Unauthorized")
or to return early from a function:
fun foo(key: String): Int {
val startingCode: String = codes.findKey(key) ?: return 0
// ...
return endingValue
}
read more: Elvis Operator
Null Operators with Related Functions
Kotlin stdlib has a series of functions that work really nicely with the operators mentioned above. For example:
// use ?.let() to change a not null value, and ?: to provide a default
val something = possibleNull?.let { it.transform() } ?: defaultSomething
// use ?.apply() to operate further on a value that is not null
possibleNull?.apply {
func1()
func2()
}
// use .takeIf or .takeUnless to turn a value null if it meets a predicate
val something = name.takeIf { it.isNotBlank() } ?: defaultName
val something = name.takeUnless { it.isBlank() } ?: defaultName
Related Topics
In Kotlin, most applications try to avoid null values, but it isn't always possible. And sometimes null makes perfect sense. Some guidelines to think about:
in some cases, it warrants different return types that include the status of the method call and the result if successful. Libraries like Result give you a success or failure result type that can also branch your code. And the Promises library for Kotlin called Kovenant does the same in the form of promises.
for collections as return types always return an empty collection instead of a null, unless you need a third state of "not present". Kotlin has helper functions such as emptyList() or emptySet() to create these empty values.
when using methods which return a nullable value for which you have a default or alternative, use the Elvis operator to provide a default value. In the case of a Map use the getOrElse() which allows a default value to be generated instead of Map method get() which returns a nullable value. Same for getOrPut()
when overriding methods from Java where Kotlin isn't sure about the nullability of the Java code, you can always drop the ? nullability from your override if you are sure what the signature and functionality should be. Therefore your overridden method is more null safe. Same for implementing Java interfaces in Kotlin, change the nullability to be what you know is valid.
look at functions that can help already, such as for String?.isNullOrEmpty() and String?.isNullOrBlank() which can operate on a nullable value safely and do what you expect. In fact, you can add your own extensions to fill in any gaps in the standard library.
assertion functions like checkNotNull() and requireNotNull() in the standard library.
helper functions like filterNotNull() which remove nulls from collections, or listOfNotNull() for returning a zero or single item list from a possibly null value.
there is a Safe (nullable) cast operator as well that allows a cast to non-nullable type return null if not possible. But I do not have a valid use case for this that isn't solved by the other methods mentioned above.
The previous answer is a hard act to follow, but here's one quick and easy way:
val something: Xyz = createPossiblyNullXyz() ?: throw RuntimeError("no it shouldn't be null")
something.foo()
If it really is never null, the exception won't happen, but if it ever is you'll see what went wrong.
I want to add that now it exists Konad library that addresses more complex situations for nullable composition. Here it follows an example usage:
val foo: Int? = 1
val bar: String? = "2"
val baz: Float? = 3.0f
fun useThem(x: Int, y: String, z: Float): Int = x + y.toInt() + z.toInt()
val result: Int? = ::useThem.curry()
.on(foo.maybe)
.on(bar.maybe)
.on(baz.maybe)
.nullable
if you want to keep it nullable, or
val result: Result<Int> = ::useThem.curry()
.on(foo.ifNull("Foo should not be null"))
.on(bar.ifNull("Bar should not be null"))
.on(baz.ifNull("Baz should not be null"))
.result
if you want to accumulate errors. See maybe section
Accepted answer contains the complete detail, here I am adding the summary
How to call functions on a variable of nullable type
val str: String? = "HELLO"
// 1. Safe call (?), makes sure you don't get NPE
val lowerCaseStr = str?.toLowerCase() // same as str == null ? null : str.toLowerCase()
// 2. non-null asserted call (!!), only use if you are sure that value is non-null
val upperCaseStr = str!!.toUpperCase() // same as str.toUpperCase() in java, NPE if str is null
How to convert nullable type variable to non-nullable type
Given that you are 100% sure that nullable variable contains non-null value
// use non-null assertion, will cause NPE if str is null
val nonNullableStr = str!! // type of nonNullableStr is String(non-nullable)
Why safe(?) or non-null(!!) assertion not required inside null check if block
if the compiler can guarantee that the variable won't change between the check and the usage then it knows that variable can't possibly be null, so you can do
if(str != null){
val upperCaseStr = str.toUpperCase() // str can't possibly be null, no need of ? or !!
}
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.