as usual F# spec to the rescue:
6.3.2 Tuple Expressions
An expression of the form expr1, ..., exprn is a tuple expression. For example:
let three = (1,2,"3")
let blastoff = (10,9,8,7,6,5,4,3,2,1,0)
The expression has the type (ty1 * ... * tyn) for fresh types ty1 … tyn, and each individual expression ei is checked using initial type tyi.
Tuple types and expressions are translated into applications of a family of F# library types named System.Tuple. Tuple types ty1 * ... * tyn are translated as follows:
- For n <= 7 the elaborated form is
Tuple<ty1,...,tyn>
. - For larger n, tuple types are shorthand for applications of the additional F# library type
System.Tuple<_>
as follows: - For n = 8 the elaborated form is
Tuple<ty1,...,ty7,Tuple<ty8>>
. - For 9 <= n the elaborated form is
Tuple<ty1,...,ty7,tyB>
where tyB is the converted form of the type (ty8 ... tyn).
Tuple expressions (expr1,...,exprn) are translated as follows:
- For n <= 7 the elaborated form
new Tuple<ty1,…,tyn>(expr1,...,exprn)
. - For n = 8 the elaborated form
new Tuple<ty1,…,ty7,Tuple<ty8>>(expr1,...,expr7, new Tuple<ty8>(expr8)
. - For 9 <= n the elaborated form
new Tuple<ty1,...ty7,ty8n>(expr1,..., expr7, new ty8n(e8n)
where ty8n is the type (ty8*...* tyn) and expr8n is the elaborated form of the expression expr8,..., exprn.
When considered as static types, tuple types are distinct from their encoded form. However, the encoded form of tuple values and types is visible in the F# type system through runtime types. For example, typeof is equivalent to typeof<System.Tuple<int,int>>
, and (1,2) has the runtime type System.Tuple<int,int>
. Likewise, (1,2,3,4,5,6,7,8,9) has the runtime type Tuple<int,int,int,int,int,int,int,Tuple<int,int>>
.
NOTE: prior to adding tuples to BCL in .NET 4.0 F# used System.Tuple type defined in FSharp.Core dll
I guess the only way for you to deal with tuples having arbitrary size is to resort to constructing and deconstructing then with functions from Microsoft.FSharp.Reflection.FSharpType\FSharpValue