Announcing F# 4.7

Phillip Carter

We’re excited to announce general availability of F# 4.7 in conjunction with the .NET Core 3.0 release! In this post, I’ll show you how to get started, explain everything in F# 4.7 and give you a sneak peek at what we’re doing for the next version of F#.

F# 4.7 is another incremental release of F# with a focus on infrastructural changes to the compiler and core library and some relaxations on previously onerous syntax requirements.

F# 4.7 was developed entirely via an open RFC (requests for comments) process. The F# community has offered very detailed feedback in discussions for this version of the language. You can view all RFCs that correspond with this release here:

Get started

First, install either:

If you are a Visual Studio user, you will get an appropriate .NET Core installed by default. Once you have installed either .NET Core or Visual Studio 2019, you can use F# 4.7 with Visual Studio, Visual Studio for Mac, or Visual Studio Code with Ionide.

FSharp.Core now targets .NET Standard 2.0

Starting with FSharp.Core 4.7.0 and F# 4.7, we’re officially dropping support for .NET Standard 1.6. Now that FSharp.Core targets .NET Standard 2.0, you can enjoy a few new goodies on .NET Core:

  • Simpler dependencies, especially if using a tool like Paket
  • FromConverter and ToConverter static methods on FSharpFunc<'T, 'TResult>
  • Implicit conversions between FSharpFunc<'T, 'TResult> and Converter<'T, 'TResult>
  • The FuncConvert.ToFSharpFunc<'T> method
  • Access to the MatchFailureException type
  • The WebExtensions namespace for working with older web APIs in an F#-friendly way

Additionally, the FSharp.Core API surface area has expanded to better support parallel and sequential asynchronous computations:

  • Async.Parallel has an optional maxDegreesOfParallelism parameter so you can tune the degree of parallelism used
  • Async.Sequential to allow sequential processing of async computations

Thanks to Fraser Waters for contributing the new FSharp.Core additions.

Support for LangVersion

F# 4.7 introduces the ability to tune your effective language version with your compiler. We’re incredibly excited about this feature, because it allows us to deliver preview features alongside released features for any given compiler release.

If you’re interested in trying out preview features and giving feedback early, it’s very easy to get started. Just set the following property in your project file:

Once you save the project file, the compiler will now give you access to all preview features that shipped with that compiler.

When using F# in preview versions of .NET Core and/or Visual Studio, the language version will be set to preview by default.

The lowest-supported language version is F# 4.6. We do not plan on retrofitting language version support for F# 4.5 and lower.

Implicit yields

In the spirit of making things easier, F# 4.7 introduces implicit yields for lists, arrays, sequences, and any Computation Expression that defines the Yield, Combine, Delay, and Zero members.

A longstanding issue with learning F# has been the need to always specify the yield keyword in F# sequence expressions. Now you can delete all the yield keywords, since they’re implicit!

This makes F# sequence expressions align with list and array expressions.

But that’s not all! Prior to F# 4.7, even with lists and arrays, if you wanted to conditionally generate values it was a requirement to specify yield everywhere, even if you only had one place you did it. All the yield keywords can now be removed:

This feature was inspired by Fable programs that use F# list expressions as HTML templating DSLs.

Of course, if you prefer writing yield, you still can, with the same rules as before.

Syntax relaxations

There are two major relaxations for F# syntax added in F# 4.7. Both should make F# code easier to write, especially for beginners.

No more required double underscore

Prior to F# 4.7, if you wanted to specify member declarations and you didn’t want to name the ‘this’ identifier on F# objects, you had to use a double underscore. Now, you can only specify a single underscore, which previous language versions would reject:

This same rule has been relaxed for C-style for loops where the indexer is not meaningful:

Thanks to Gustavo Leon for contributing this feature.

Indentation relaxations for parameters passed to constructors and static methods

Another annoyance with previous F# compilers was a requirement to indent parameters to constructors or static methods. This was due to an old rule in the compiler where the first parameter determined the level of indentation required for the rest of the parameters. This is now relaxed:

Preview features

As I mentioned previously, F# 4.7 introduces the concept of an effective language version for the compiler. In the spirit of shipping previews as early as possible, we’ve included two new preview features: nameof and opening of static classes.

Nameof

The nameof function has been of the most-requested feature to add to F#. It’s very convenient when you want to log the names of things (like parameters or classes) and have the name change as you’d expect if you refactor those symbols to use different names over time. We’re still not 100% resolute on the design of it, but the core functionality is good enough that we’d love people to try it out and give us feedback. Here’s a little taste of what you can do with it:

You can also contribute to its design by proposing changes to the corresponding RFC.

Open static classes

Much like nameof, opening of static classes has been requested a lot. Not only does it allow better usage of C# APIs that assume the ability to open static classes, it can also improve F# DSLs. However, we’re also not 100% resolute on its overall design. Here’s a little taste of what it’s like:

You can also contribute to its design by proposing changes to the corresponding RFC.

F# Interactive for .NET Core Preview

Starting with F# 4.7 and .NET Core 3, you can now use F# interactive (FSI) from .NET Core! Just open a command line and type dotnet fsi to get started.

The FSI experience for .NET Core is now a very, very stable preview. There are still some quirks with dependency resolution when pulling in packages and their transitive references. We’re addressing these by adding #r “nuget:package-name” support for FSI, and we’re hoping that you’ll transition away from manually referencing third-party .dlls and instead using packages as the unit of reference for FSI.

This package management support is still only available in nightly builds of the compiler. It will become available for general usage in forthcoming support for Jupyter Notebooks via the .NET Kernel and in the first preview of .NET 5.

Updates to F# tools for Visual Studio

The Visual Studio 2019 update 16.3 release corresponds with F# 4.7 and .NET Core 3. In this release, we’ve made tooltips a bit nicer and fixed some longstanding issues in the compiler and tools that affect your experience in Visual Studio. We also spent a lot of time doing more infrastructural work to make the F# integration with Roslyn significantly more stable than it was in the past.

Record definition tooltips use a more canonical formatting:

Anonymous Records also do the same:

And record value output in FSI also uses a more canonical form:

Properties with explicit get/set modifiers will also reflect those modifiers in tooltips:

Looking back at the past year or so of F# evolution

The past year (plus a few months) has seen a lot of additions to the F# language and tools. We’ve shipped:

  • F# 4.5, F# 4.6, and now F# 4.7 with 14 new language features between the three of them
  • 6 updates to the Visual Studio tools for F#
  • Massive performance improvements to F# tooling for larger codebases
  • 2 preview features for the next version of F#
  • A revamped versioning scheme for FSharp.Core
  • A new home for F# OSS development under the .NET Foundation

It’s been quite a rush, and while the sheer number of updates and fundamental shifts to F#, we’re planning on ramping up these efforts!

Looking head towards F# 5 and .NET 5

As .NET undergoes a monumental shift towards .NET 5, F# will also feature a bit of a shift. While F# is a general-purpose language – the functional programming language for .NET – it also has a strong heritage of being used for “analytical” workloads: processing data, doing numerical work, data science and machine learning, etc. We feel that F# is positioned extremely well to continue this path, and we intend on emphasizing features that can align with these workloads more.

Some of the concrete things we’ll focus on is making F# a first-class language for Jupyter Notebooks via the .NET Kernel. We’ll also emphasize language features that make it easier to work with collections of data.

I like to think of these things as being “in addition to” everything F# is focused on so far: first-class .NET support, excellent tooling, wonderful features that make general purpose F# programming great, and now an influx of work aligned with “analytical” programming. We’re incredibly excited about the work ahead of us, and we hope you’ll also contribute in the way you see best.

Cheers, and happy hacking!

21 comments

Discussion is closed. Login to edit/delete existing comments.

  • Vsevolod Ostapenko 0

    Just tried dotnet fsi in .NET SDK 3.0 on my Mac with OSX 10.14.6. Immediately stepped onto a presumably fixed issue – https://github.com/dotnet/fsharp/issues/7277 (“dotnet fsi complaining about missing Mono.Posix assembly”).

  • Tony Henrique 0

    Awesome!

  • Gulshanur Rahman 0

    Maybe for .net 5, target Python devs? Whatever they do with Python, make it simpler/easier/more intuitive to do in F#, with greater tooling support. How about Python interop?

    • Phillip CarterMicrosoft employee 0

      Hey Gulshanur,

      Python interop isn’t on the immediate roadmap (such a thing would likely be a .NET runtime concept, not a language one). But we are focusing on some of the things that make Python nice for analytical work and using that as an influence for work in F#.

    • Jay Tuley 0

      If you use pythonnet, the docs show how to use it with c# dynamic keyword. In f# you can use the FSharp.Interop.Dynamic library. https://github.com/fsprojects/FSharp.Interop.Dynamic
      “`
      open Python.Runtime
      open FSharp.Interop.Dynamic
      open FSharp.Interop.Dynamic.Operators

      do
      use __ = Py.GIL()
      let np = Py.Import(“math”)
      np?cos(np?pi ?*? 2) |> printfn “%O”
      let sin = np?sin
      sin 5 |> printfn “%O”
      np?cos(5) ?+? sin(5) |> printfn “%O”
      “`

  • Wil Wilder Apaza Bustamante 0

    Can you expand on this sentence? We’ll also emphasize language features that make it easier to work with collections of data.
    Where can I read language proposals, for example.
    Thanks!

  • Eugene Ivanoff 0

    Will there be support for WPF, WinForms and ASP.NET Core web applications?

    • Phillip CarterMicrosoft employee 0

      Hey Eugue,

      There are no current plans for templates or designer support for WPF or WinForms. But you can certainly call the APIs in F# code. F# is already fully supported for ASP.NET Core, though we don’t surface templates with Razor files because those take a dependency on being in a C# project right now.

  • James Roberts 0

    I’m coming back to F# after being away for a few years. I took a refresher on some of the fundamentals and came across one of those nasty F#’ish issues that makes me crazy. I’m trying to chart a line and can’t seem to find any Charting tools compatible with 3.0. Am I too early to the game to try an do some plotting? Or (more likely) am I not being resourceful enough in finding a compatible library? Any advice would be so helpful. I will give you my first and second born just to show my gratitude. 🙂

    • Isaac Abraham 0

      Hey James

      You could do worse than try XPlot (https://fslab.org/XPlot/), which has both Plotly and GoogleCharts APIs. Both versions support NET Standard 2.0 as far as I’m aware so you should be good to go!

  • Robert Boissy 0

    Looking ahead towards F# 5 and .NET 5

    At the Xilinx Developer Forum today MSFT announced a new family of Azure VMs that will include 1-4 Xilinx Alveo U250 FPGAs. Xilinx also announced Vitis, a comprehensive open development framework that is designed for software developers to create, port, and consume hardware-accelerated logic.

    https://www.servethehome.com/xdf19-xilinx-vitis-unified-software-platform-launched/
    https://developer.xilinx.com/

    My understanding is that most of Azure’s FPGA nodes use Intel (Altera) FPGA hardware. Azure will no doubt also support Intel’s forthcoming Agilex family of Xeon CPU/FPGA semiconductors with on-die integration. Nevertheless, Xilinx is the major FPGA hardware company.

    Lombiq’s Hastlayer effort (which even implements posits!) is interesting (and supports Xilinx FPGAs). But a more substantial effort to enable .NET 5 to consume Xilinx FPGA functionality through Vitis would be very welcome!

  • rei miyasaka 0

    Woo! #r nuget!

  • Jorge Branco 0

    Can someone please explain me how to get this thing working on Ubuntu?

    I installed dotnetcore 3.0 as indicated but fsharpc still tells me “F# Compiler for F# 4.0 (Open Source Edition)” (most likely from a previous installation I had done with “sudo apt install fsharp”).

    The above text refers that after installing dotnetcore 3.0, F# 4.7 will be available on Visual Studio.
    But I don’t have Visual Studio and I’m not even remotely interested in installing Visual Studio — in fact, I don’t even understand why you’re bundling both things together. Wasn’t the point of the new move of Microsoft to decouple both products?

    It crossed my mind I could go to the “Releases” page of the GitHub’s F# project but alas, it’s again only talking about “Visual Studio” releases. What’s this?

    I’m confused..

    • Phillip CarterMicrosoft employee 0

      Hello Jorge,

      fsharpc is the name of the F# compiler packaged in Mono, not .NET Core. If you use dotnet build it will call the .NET Core compiler for F#, which is what you should use.

  • Casper Bollen 0

    This is not working on Visual Studio for mac. The implicit yields result in ‘ignored’ warnings. Switched to the preview branch to update VS, still no luck.

    When trying VS code, I can use the new yield syntax, but then I get ‘Unable to find the file ‘System.ComponentModel.Composition’. So, again, with F# on Mac no luck (never seemed to work in the past either).

    • Phillip CarterMicrosoft employee 0

      Hello, VS for Mac does not support F# 4.7 yet.

      Can you share a repro for the error you are seeing? The new syntax does not depend on

      System.ComponentModel.Composition

      nor does any part of the Ionide extension for F#. I suspect you are using something that depends on a version of MEF that doesn’t work with .NET Core. Have you tried creating a new .NET Core project and using VSCode for that?

      • Casper Bollen 0

        Thanks for taking the time to reply!

        I think implicit yields are great, so I was eager to use them. The libraries the problem occurs are:

        https://github.com/halcwb/GenUtils
        https://github.com/halcwb/GenSolver

        Checkout the dotnetcore or vs2019 branches.

        They both use only these dependencies:

        nuget MathNet.Numerics.FSharp

        nuget FSharp.Formatting
        nuget FSharp.Formatting.CommandTool

        nuget Unquote
        nuget Expecto
        nuget Expecto.BenchmarkDotNet
        nuget Expecto.FsCheck
        nuget Expecto.Hopac

        I can also not imagine which of the libs require MEF?

      • Casper Bollen 0

        It’s now more than 5 months later, and still is F# 4.7 not supported!! I think this is a shame and I wonder whether Microsoft takes F# as a language seriously. Please fix this ASAP.

Feedback usabilla icon