I wonder what this means in F#.
“a function taking an integer,
which returns a function which takes an integer and returns an integer.”
But I don't understand this well.
Can anyone explain this so clear ?
[Update]:
> let f1 x y = x+y ;;
val f1 : int -> int -> int
What this mean ?
Let's begin from the beginning.
F# uses the colon (:
) notation to indicate types of things. Let's say you define a value of type int
:
let myNumber = 5
F# Interactive will understand that myNumber
is an integer, and will tell you this by:
myNumber : int
which is read as
myNumber
is of typeint
So far so good. Let's introduce something else, functional types. A functional type is simply the type of a function. F# uses ->
to denote a functional type. This arrow symbolizes that what is written on its left-hand side is transformed into what is written into its right-hand side.
Let's consider a simple function, that takes one argument and transforms it into one output. An example of such a function would be:
isEven : int -> bool
This introduces the name of the function (on the left of the :
), and its type. This line can be read in English as:
isEven
is of type function that transforms anint
into abool
.
Note that to correctly interpret what is being said, you should make a short pause just after the part "is of type", and then read the rest of the sentence at once, without pausing.
In F#, functions are (almost) no more special than ordinary types. They are things that you can pass around to functions, return from functions, just like bools, ints or strings.
So if you have:
myNumber : int
isEven : int -> bool
You should consider int
and int -> bool
as two entities of the same kind: types. Here, myNumber
is a value of type int
, and isEven
is a value of type int -> bool
(this is what I'm trying to symbolize when I talk about the short pause above).
Values of types that contain ->
happens to be also called functions, and have special powers: you can apply a function to a value. So, for example,
isEven myNumber
means that you are applying the function called isEven
to the value myNumber
. As you can expect by inspecting the type of isEven
, it will return a boolean value. If you have correctly implemented isEven
, it would obviously return false
.
Let's define a generic function to determine is an integer is multiple of some other integer. We can imagine that our function's type will be (the parenthesis are here to help you understand, they might or might not be present, they have a special meaning):
isMultipleOf : int -> (int -> bool)
As you can guess, this is read as:
isMultipleOf
is of type (PAUSE) function that transforms anint
into (PAUSE) function that transforms anint
into abool
.
(here the (PAUSE) denote the pauses when reading out loud).
We will define this function later. Before that, let's see how we can use it:
let isEven = isMultipleOf 2
F# interactive would answer:
isEven : int -> bool
which is read as
isEven
is of typeint -> bool
Here, isEven
has type int -> bool
, since we have just given the value 2 (int
) to isMultipleOf
, which, as we have already seen, transforms an int
into an int -> bool
.
We can view this function isMultipleOf
as a sort of function creator.
isMultipleOf
So now let's define this mystical function-creating function.
let isMultipleOf n x =
(x % n) = 0
Easy, huh?
If you type this into F# Interactive, it will answer:
isMultipleOf : int -> int -> bool
Note that there are no parenthesis. This is not particularly important for you now. Just remember that the arrows are right associative. That is, if you have
a -> b -> c
you should interpret it as
a -> (b -> c)
The right in right associative means that you should interpret as if there were parenthesis around the rightmost operator. So:
a -> b -> c -> d
should be interpreted as
a -> (b -> (c -> d))
isMultipleOf
So, as you have seen, we can use isMultipleOf
to create new functions:
let isEven = isMultipleOf 2
let isOdd = not << isEven
let isMultipleOfThree = isMultipleOf 3
let endsWithZero = isMultipleOf 10
F# Interactive would respond:
isEven : int -> bool
isOdd : int -> bool
isMultipleOfThree : int -> bool
endsWithZero : int -> bool
But you can use it differently. If you don't want to (or need to) create a new function, you can use it as follows:
isMultipleOf 10 150
This would return true
, as 150 is multiple of 10. This is exactly the same as create the function endsWithZero
and then applying it to the value 150.
Actually, function application is left associative, which means that the line above should be interpreted as:
(isMultipleOf 10) 150
That is, you put the parenthesis around the leftmost function application.
Now, if you can understand all this, your example (which is the canonical CreateAdder
) should be trivial!
Sometime ago someone asked this question which deals with exactly the same concept, but in Javascript. In my answer I give two canonical examples (CreateAdder, CreateMultiplier) inf Javascript, that are somewhat more explicit about returning functions.
I hope this helps.
The canonical example of this is probably an "adder creator" - a function which, given a number (e.g. 3) returns another function which takes an integer and adds the first number to it.
So, for example, in pseudo-code
x = CreateAdder(3)
x(5) // returns 8
x(10) // returns 13
CreateAdder(20)(30) // returns 50
I'm not quite comfortable enough in F# to try to write it without checking it, but the C# would be something like:
public static Func<int, int> CreateAdder(int amountToAdd)
{
return x => x + amountToAdd;
}
Does that help?
EDIT: As Bruno noted, the example you've given in your question is exactly the example I've given C# code for, so the above pseudocode would become:
let x = f1 3
x 5 // Result: 8
x 10 // Result: 13
f1 20 30 // Result: 50
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With