I noticed a quite weird behavior of the System.Tuple.Create
method in F#. When looking at the MSDN documentation it indicates that the return type is of System.Tuple<T>
. However when using this method in F# all overloads except Tuple.Create(T)
will return 'T1 * 'T2
. Obviously invoking the Tuple<T>
constructor will return Tuple<T>
. But I don't understand how the return type of the Tuple.Create
is different in F#.
The tuple type of F# (a syntactic tuple) is compiled as System.Tuple<..>
. So they are the same type at .NET level but for F# type system they are different types: the type of a syntactic tuple will not match the type of a System.Tuple<..>
but their runtime type will be the same.
You can find a detailed description in the F# spec
The example with new System.Tuple<'t>()
does not return a syntactic tuple, probably because you are instantiating explicitly a specific type and you should get back exactly that.
Here are some tests:
let x = new System.Tuple<_,_>(2,3) // Creates a Tuple<int,int>
let y = System.Tuple.Create(2,3) // Creates a syntactic tuple int * int
let areEqual = x.GetType() = y.GetType() // true
let f (x:System.Tuple<int,int>) = ()
let g (x:int * int) = ()
let a = f x
let b = g y
// but
let c = f y
//error FS0001: The type 'int * int' is not compatible with the type 'Tuple<int,int>'
let d = g x
// error FS0001: This expression was expected to have type int * int but here has type Tuple<int,int>
So, at compile time they are different but at runtime they are the same. That's why when you use .GetType()
you get the same result.