Tuple.Create in F#

490 views Asked by At

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#.

1

There are 1 answers

2
Gus On BEST ANSWER

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.