Your assumption is correct, in this case, the functions are exactly the same.
You can see that by inspecting the generated IL code (as demonstrated by Craig) and you can also see that by looking at the type inferred by the F# compiler. In both cases, you'll see int -> int -> int
. The F# language views that as a function that takes int
and returns int -> int
but it is actually compiled as a method with multiple arguments (for efficiency).
If you write fun
immediately following let .. =
then the compiler turns that into a standard function. However, you can write code that is a bit different if you do some computation before returning the function:
let f1 a b = printfn "hi"; a + b
let f2 a = printfn "hi"; (fun b -> a + b)
Now the two functions are very different, because the second one prints "hi" when you give it just a single argument (and then it returns a function that you can call):
> let f = f2 1;;
hi // The body is called, prints
val f : (int -> int) // and returns function
> f 2;; // This runs the body of 'fun'
val it : int = 3 // which performs the additiion
You can write the same code using f1
, but the first command will just create a new function and the second command will print "hi" and do the addition.
In this case, the generated IL code for f2
will be different. It will be a function that returns a function (of type FSharpFunc<int, int>
). The type displayed by F# is also different - it will be int -> (int -> int)
instead of int -> int -> int
. You can use values of these two types in exactly the same ways, but it hints you that the first one may do some effects when you give it a single argument.