Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News F# 4.1 Brings Improvements and Interoperation with C# 7

F# 4.1 Brings Improvements and Interoperation with C# 7

F# 4.1 brings improvements to the language. It is distributed through the Microsoft tools for F#, which are stated to ship later this year. This version enables support for struct tuples, interoperation with C# 7 and by-ref returns.

Tuples are commonly used in F#, as the syntax and type inference make them easy to use. They are reference types, stored on the heap. F# 4.1 brings struct tuples, stored on the stack. This has performance benefits for certain scenarios, such as allocating a large number of small tuples.

To support the ValueTuple type, tuple types, tuple expressions and tuple patterns can now be annotated with the struct keyword.

 // Creating a new struct tuple.
let origin = struct (0, 0)

// Take struct tuples as arguments to a function and generate a new struct tuple.
let getPointFromOffset (point: struct (x, y)) (offset: struct (dx, dy)) = 
    struct (x + dx, y + dy)

// Pattern match on a struct tuple.
let doAMatch (input: struct (x, y)) =
    match input with
    | struct (0, 0) -> sprintf "The tuple is the origin!"
    | struct (_, _) -> sprintf "The tuple is NOT the origin!"

Interoperation with C# 7 also works using the struct keyword.

// Calls a C# function returning a value tuple
let struct(word, value) = SomeService.SomeResult()
// Calls a C# function taking a value tuple in parameter.
let result = SomeService.CreateResult(struct("hello", 12))

In addition to tuples, record types and discriminated unions can also be represented as value types. It requires the struct annotation.

 type Student = {
    Id: int
    Name: string
    Age: int
    GPA: double
    Major: string

type Shape = 
| Circle of radius: float
| Square of side: int
| Rectangle of sides: double*double

F# 4.1 also brings by-ref returns. F# already has support for ref locals, but had no support for consuming or generating byref-returning methods.

// Returns from an array.
let f (x:int[]) = &x.[0]

// Returns from a record
type R = { mutable z : int }
let f (x:byref<R>) = &x.z

By-ref returns can also be consumed from a C# method.

public static ref int Find(int val, int[] vals)
        for (int i = 0; i < vals.Length; i++)
            if (vals[i] == val)
                return ref numbers[i];

// 'result' is of type 'byref<int>'.
let result = SomeCSharpClass.Find(3, [| 1; 2; 3; 4; 5 |])

In addition to the F# source code on GitHub, the language specifications are also available publicly for more information.

Rate this Article