What's new in F# 4.7

F# 4.7 adds multiple improvements to the F# language.

Get started

F# 4.7 is available in all .NET Core distributions and Visual Studio tooling. Get started with F# to learn more.

Language version

The F# 4.7 compiler introduces the ability to set your effective language version via a property in your project file:

<PropertyGroup>
    <LangVersion>preview</LangVersion>
</PropertyGroup>

You can set it to the values 4.6, 4.7, latest, and preview. The default is latest.

If you set it to preview, your compiler will activate all F# preview features that are implemented in your compiler.

Implicit yields

You no longer need to apply the yield keyword in arrays, lists, sequences, or computation expressions where the type can be inferred. In the following example, both expressions required the yield statement for each entry prior to F# 4.7:

let s = seq { 1; 2; 3; 4; 5 }

let daysOfWeek includeWeekend =
    [ 
        "Monday"
        "Tuesday"
        "Wednesday"
        "Thursday"
        "Friday"
        if includeWeekend then 
            "Saturday"
            "Sunday"
    ] 

If you introduce a single yield keyword, every other item must also have yield applied to it.

Implicit yields are not activated when used in an expression that also uses yield! to do something like flatten a sequence. You must continue to use yield today in these cases.

Wildcard identifiers

In F# code involving classes, the self-identifier needs to always be explicit in member declarations. But in cases where the self-identifier is never used, it has traditionally been convention to use a double-underscore to indicate a nameless self-identifiers. You can now use a single underscore:

type C() =
    member _.M() = ()

This also applies for for loops:

for _ in 1..10 do printfn "Hello!"

Indentation relaxations

Prior to F# 4.7, the indentation requirements for primary constructor and static member arguments required excessive indentation. They now only require a single indentation scope:

type OffsideCheck(a:int,
    b:int, c:int,
    d:int) = class end

type C() =
    static member M(a:int,
        b:int, c:int,
        d:int) = 1