A 2-tuple or a 3-tuple represent a group of related items. (Points in 2D space, RGB values of a color, etc.) A 1-tuple is not very useful since it could easily be replaced with a single int
.
A 0-tuple seems even more useless since it contains absolutely nothing. Yet it has properties that make it very useful in functional languages like F#. For example, the 0-tuple type has exactly one value, usually represented as ()
. All 0-tuples have this value so it's essentially a singleton type. In most functional programming languages, including F#, this is called the unit
type.
Functions that return void
in C# will return the unit
type in F#:
let printResult = printfn "Hello"
Run that in the F# interactive interpreter, and you'll see:
val printResult : unit = ()
This means that the value printResult
is of type unit
, and has the value ()
(the empty tuple, the one and only value of the unit
type).
Functions can take the unit
type as a parameter, too. In F#, functions may look like they're taking no parameters. But in fact, they're taking a single parameter of type unit
. This function:
let doMath() = 2 + 4
is actually equivalent to:
let doMath () = 2 + 4
That is, a function that takes one parameter of type unit
and returns the int
value 6. If you look at the type signature that the F# interactive interpreter prints when you define this function, you'll see:
val doMath : unit -> int
The fact that all functions will take at least one parameter and return a value, even if that value is sometimes a "useless" value like ()
, means that function composition is a lot easier in F# than in languages that don't have the unit
type. But that's a more advanced subject which we'll get to later on. For now, just remember that when you see unit
in a function signature, or ()
in a function's parameters, that's the 0-tuple type that serves as the way to say "This function takes, or returns, no meaningful values."