You motivate the question using a somewhat arbitrary example. I assume that your actual motivation for wanting this is something more tricky and it would be good to know what that actual motivation is - because it might be useful in giving a good answer.
First, if you want to work with a tuples of arbitrary length, you should probably not be using tuples. F# tuples are fixed (statically known) length. Other uses of them will be cumbersome. (Unlike in some dynamic languages where tuples are used for arbitrary-lenght data more frequently.) Second, if you do not know the type at compile-time, I'm not sure what you want to achieve via unboxing.
Depedning on your actual motivation, there is one trick that may be helpful. The trick is to invoke a generic method via reflection, passing it the unboxed values.
If we assume that all elements of your tuple have the same type, you can take them as an array (of unboxed, but generic values):
type Helper =
static member Process<'T>(data:'T[]) =
typeof<'T>.Name
Now you can invoke Helper.Process
using reflection:
open Microsoft.FSharp.Reflection
let a = (1., 2.)
let tys = FSharpType.GetTupleElements(a.GetType())
for ty in tys do if ty <> tys.[0] then failwith "All types must be the same"
let flds = FSharpValue.GetTupleFields(a)
let arr = System.Array.CreateInstance(tys.[0], flds.Length)
System.Array.Copy(flds, arr, flds.Length)
typeof<Helper>.GetMethod("Process")
.MakeGenericMethod([| tys.[0] |]).Invoke(null, [| arr |] )
This returns "Double"
, because when called via reflection, the type of 'T
will be Double
, so you are actually getting the values as unboxed.
There are some rare cases where a thing like this is useful, but my guess is that you do not actually need this and, instead, you'd be probably better off with a different way of representing your data.