OK, so you define a function that takes 2 parameters, but you actually get a function that takes 1 parameter, and returns a function that will take the second parameter and return the final result. Hmm, this raises lots of questions.
What happens if the function has more than two parameters?
>let f a b c = a + b + c
is of type
val f : int -> int -> int -> int
So we get a chain of functions, each one taking exactly one parameter, and returning a function that takes the next.
If there are more that 2 parameters, can I partially apply more than one at a time?
Following on from above, we can do:
>let g = f 1 2
val g : (int -> int)
>g 3
val it : int = 6
This looks like F# functions can just accept a subset of their arguments, but remember that as f returns a function, what is really happening is the equivalent of this:
let g = (f 1) 2
We are making a sequence of function calls. We could make the exact call like this:
((f 1) 2) 3
The consequence of this is that we can’t partially apply any sub-set of the arguments. We still have to call the function chain in the correct order, which partially apply the arguments strictly from left to right.
What happens to the partially applied arguments?
They are captured forever and immutably in the returned function.
let f a b = a + b
let g = f 1
let h = f 10
g will always return its argument plus 1, h always plus 10. f did not return the same function when called with different arguments.
Strange as this last point seems to those of us more used to C#, this notion of capturing values into functions does exist in C#. Anonymous delegates capture the values of variables from their declaring method. In C# 3.0, lambda functions are a simpler syntax for these anonymous delegates. Here is an example.
static void Main(string[] args)
{
var g = f(1);
var h = f(10);
Console.WriteLine(”g(5) = {0}”, g(5));
Console.WriteLine(”h(5) = {0}”, h(5));
Console.WriteLine(”f(3)(5) = {0}”, f(3)(5));
}
static Func<int, int> f(int a)
{
return new Func<int, int>(x => x + a);
}
Similar result, ugly code!