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
andToConverter
static methods onFSharpFunc<'T, 'TResult>
- Implicit conversions between
FSharpFunc<'T, 'TResult>
andConverter<'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!
Are there any plans to add language support for high kinded types, similar to Haskell and Scala?
This may require a CLR change.
You can track the feature here (though it’s a proposal of C#): https://github.com/dotnet/csharplang/issues/339
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).
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
<code>
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?
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.
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?
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...
Hello Jorge,
fsharpc
is the name of the F# compiler packaged in Mono, not .NET Core. If you usedotnet build
it will call the .NET Core compiler for F#, which is what you should use.Woo! #r nuget!
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...
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...
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!
Will there be support for WPF, WinForms and ASP.NET Core web applications?
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.
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!
Hey Daniel,
You can find all suggestions here: https://github.com/fsharp/fslang-suggestions
And all RFCs here: https://github.com/fsharp/fslang-design
Something that’s currently in-progress is making slices more consistent across built-in collection types and supporting “from the end” slicing.
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?
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”
“`
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#.
Awesome!