{"id":30567,"date":"2020-11-10T09:10:07","date_gmt":"2020-11-10T16:10:07","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=30567"},"modified":"2025-09-26T15:04:38","modified_gmt":"2025-09-26T22:04:38","slug":"announcing-f-5","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-f-5\/","title":{"rendered":"Announcing F# 5"},"content":{"rendered":"<p>Today, we&#8217;re excited to announce the general availability of F# 5. It ships with <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-5-0\">.NET 5<\/a>. We&#8217;ve been working on F# 5 for over the past year now, and we&#8217;re excited to share it with everyone.<\/p>\n<p>You can get F# 5 in the following ways:<\/p>\n<ul>\n<li><a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet-core\/5.0\">Install the latest .NET 5 SDK<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/interactive\/#jupyter-and-nteract\">Install .NET for Jupyter\/nteract<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/interactive\/#visual-studio-code\">Install .NET for VSCode Notebooks<\/a><\/li>\n<\/ul>\n<p>If you\u2019re using Visual Studio on Windows, you\u2019ll need to upgrade to the <a href=\"https:\/\/visualstudio.microsoft.com\/downloads\/\">latest 16.8 release<\/a>.<\/p>\n<h2>What F# 5 is all about<\/h2>\n<p>From <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-f-4-1-and-the-visual-f-tools-for-visual-studio-2017-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">F# 4.1 <\/a>to F# 5, the chief focus for F# has been bringing up great support for .NET Core (now .NET 5). With F# 5, we&#8217;re considering this journey mostly complete. F# 5 marks the start of a new era of F# evolution centered around three main things:<\/p>\n<ol>\n<li>Interactive programming<\/li>\n<li>Making analytical-oriented programming convenient and fun<\/li>\n<li>Great fundamentals and performance for functional programming on .NET<\/li>\n<\/ol>\n<p>We started F# 5 with roughly these same goals, stating in the first preview that <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-f-5-preview-1\/#f-5-is-focused-on-better-interactive-and-analytical-programming\">&#8220;F# 5 is focused on better interactive and analytical programming&#8221;<\/a>. This remains true, and we also added a few more orthogonal features that everyone can enjoy regardless of how they&#8217;re using F#.<\/p>\n<h2>Using F# 5<\/h2>\n<p>F# 5 is the new default language version for the .NET SDK and Visual Studio. Any new or existing project compiled with either of those toolsets will use F# 5.<\/p>\n<p>You can also use F# 5 in the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/net-interactive-is-here-net-notebooks-preview-2\/\">.NET and Jupyter Notebooks support<\/a>.<\/p>\n<p>Check out the <a href=\"https:\/\/github.com\/cartermp\/fs5preview\">sample repository<\/a> that shows off some of what you can do with F# 5. You can play with each of the features there instead of starting from scratch.<\/p>\n<h2>FSharp.Core now targets netstandard2.0 only<\/h2>\n<p>Starting with F# 5, <a href=\"https:\/\/www.nuget.org\/packages\/FSharp.Core\/\" target=\"_blank\" rel=\"noopener noreferrer\">FSharp.Core 5.0.0 <\/a>and higher now only targets .NET Standard 2.0. We have dropped out .NET Framework 4.5 target and its dependencies to simplify the package and continue to modernize F#.<\/p>\n<p>If you are using F# on .NET Framework 4.7 or older, you should retarget to .NET Framework 4.7.2 or higher. If you cannot do so, then you should explicitly pin your FSharp.Core reference(s) to an older version, and it is also likely that F# 5 is not the best choice for you right now.<\/p>\n<p>If you were targeting .NET Core or .NET Standard already, nothing is different, since you have already been using the .NET Standard 2.0 build of FSharp.Core this entire time.<\/p>\n<h2>Package references in F# scripts<\/h2>\n<p>F# 5 brings support for package references in F# scripts with <code>#r \"nuget:...\"<\/code> syntax. Here&#8217;s how it looks for most packages:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/6a93ccf9a24ac0bd7760d271289ccf56.js\"><\/script><\/p>\n<p>Package references support packages with native dependencies, such as ML.NET.<\/p>\n<p>Package references also support packages with special requirements about referencing dependent <code>.dll<\/code>s. For example, the <a href=\"https:\/\/www.nuget.org\/packages\/FParsec\/\">FParsec<\/a> package used to require that users manually ensure that its dependent <code>FParsecCS.dll<\/code> was referenced first before <code>FParsec.dll<\/code> was referenced in F# Interactive. This is no longer needed, and you can simply just reference the package like this:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/9edcd5855a1eb453a4156e378d39f6a3.js\"><\/script><\/p>\n<p>Package references are the basis for acquiring any package when using F# in Jupyter Notebooks or VSCode Notebooks.<\/p>\n<p>Special thanks to <a href=\"https:\/\/github.com\/forki\" target=\"_blank\" rel=\"noopener noreferrer\">Steffen Forkmann<\/a> for supplying a prototype of this feature several years ago, of which much of the final implementation is still based on. Another special thanks to <a href=\"https:\/\/github.com\/smoothdeveloper\" target=\"_blank\" rel=\"noopener noreferrer\">Gauthier Segay<\/a> for the initial implementation of an extensibility mechanism for the feature, which can be used to &#8220;plug in&#8221; other dependency managers in the future.<\/p>\n<h2>Support for Jupyter, nteract, and VSCode Notebooks<\/h2>\n<p>To coincide with package references, F# 5 is fully supported in <a href=\"https:\/\/jupyter.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Jupyter Notebooks<\/a>, <a href=\"https:\/\/nteract.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">nteract<\/a>, and VSCode Notebooks.<\/p>\n<p>Here&#8217;s an example of what the VSCode Notebooks support looks like:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/11\/fsharp-package-vscode-notebooks.png\" alt=\"F# package reference and code in a VSCode notebook cell\" \/><\/p>\n<p>It also supports inline charting:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/11\/fsharp-charting-vscode-notebooks.png\" alt=\"F# plotting code generating a chart in VSCode notebooks\" \/><\/p>\n<p>And allows you to import and export Jupyter Notebooks:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/11\/net-interactive-menu.png\" alt=\"Menu showing import and export for jupyter notebooks\" \/><\/p>\n<p>VSCode Notebooks themselves are still in preview, but they already support quite a few features:<\/p>\n<ul>\n<li>Preliminary language service support<\/li>\n<li>Inline charting and formatting of data<\/li>\n<li>Compact data format (<code>.dib<\/code>) that makes code review easy<\/li>\n<li>Ability to import Jupyter notebooks (<code>.ipynb<\/code>) and convert to a <code>.dib<\/code><\/li>\n<li>Ability to export a <code>.dib<\/code> notebook as a Jupyter notebook (<code>.ipynb<\/code>)<\/li>\n<li>Sharing F#-defined values with JavaScript cells<\/li>\n<li>Sharing F#-defined values with C# cells<\/li>\n<\/ul>\n<p>There are more features on the roadmap:<\/p>\n<ul>\n<li>Better IntelliSense<\/li>\n<li>Sharing more complex data between languages<\/li>\n<\/ul>\n<p>We&#8217;d love to have you try it out and give us feedback on what you feel needs to be there. To do so, follow the <a href=\"https:\/\/github.com\/dotnet\/interactive\/blob\/master\/src\/dotnet-interactive-vscode\/README.md\">installation instructions<\/a> and don&#8217;t be shy when filing issues on GitHub!<\/p>\n<h2>String Interpolation<\/h2>\n<p>String Interpolation is one of the most highly-requested language features and the very first feature that we had an initial design for in the <a href=\"https:\/\/github.com\/fsharp\/fslang-design\">F# Language Design repository<\/a>. The design has undergone a lot of discussion over the years, but finally a breakthrough on how to best handle it was made by <a href=\"https:\/\/github.com\/yatli\">Yatao Li<\/a>, who also supplied an initial implementation.<\/p>\n<p>F# interpolated strings are fairly similar to C# or JavaScript interpolated strings, in that they let you write code in &#8220;holes&#8221; inside of a string literal. Here&#8217;s a basic example:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/4ed6b98cf35c650bef637b82efd26dc6.js\"><\/script><\/p>\n<p>However, F# interpolated strings also allow for typed interpolations, just like the <code>sprintf<\/code> function, to enforce that an expression inside of an interpolated context conforms to a particular type. It uses the same format specifiers.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/af61c08e3b2b6bfb810d7302b50a0328.js\"><\/script><\/p>\n<p>For more advanced usage, you can write multiple expressions inside of an interpolation (and technically almost an entire program). That said, it&#8217;s usually better to keep function definitions outside of interpolated strings as much as possible!<\/p>\n<h2>Support for nameof<\/h2>\n<p>Another highly-requested feature of F# 5 is <code>nameof<\/code> which resolves the symbol it&#8217;s being used for and produces its name in F# source. This is useful in various scenarios, such as logging, and protects your logging against changes in source code.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/d3bb6ffadc7751b1616e42f3f96fbcb8.js\"><\/script><\/p>\n<p>The last line will throw an exception and &#8220;month&#8221; will be shown in the error message.<\/p>\n<p>You can take a name of nearly everything in F#:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/678dc8cde08565cbbb9726a0e65ffbdd.js\"><\/script><\/p>\n<p>Three final additions are changes to how operators work: the addition of the <code>nameof&lt;'type-parameter&gt;<\/code> form for generic type parameters, and the ability to use <code>nameof<\/code> as a pattern in a pattern match expression.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/4b633fb5ad214a2538d0dd93a7b794ad.js\"><\/script><\/p>\n<p>The <code>nameof&lt;'type-parameter&gt;<\/code> form aligns with how <code>typeof<\/code> and <code>typedefof<\/code> work in F# today.<\/p>\n<h2>Open Type declarations<\/h2>\n<p>F# 5 also adds support for open type declarations. An open type declaration is like opening a static class in C#, except with some different syntax and some slightly different behavior to fit F# semantics.<\/p>\n<p>With Open Type Declarations, you can <code>open<\/code> any type to expose static contents inside of it. Additionally, you can <code>open<\/code> F#-defined unions and records to expose their contents. For example, this can be useful if you have a union defined in a module and want to access its cases, but don&#8217;t want to open the entire module.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/b2a30361927427314ab781c1bb30be98.js\"><\/script><\/p>\n<h2>Enhanced Slicing<\/h2>\n<p>Slicing data types is critical when doing analytical work on sets of data. To that end, we enhanced F# slicing in two areas for release, with one still considered preview.<\/p>\n<h3>Consistent behavior for built-in data types<\/h3>\n<p>Behavior for slicing the built-in FSharp.Core data types (array, list, string, 2D array, 3D array, 4D array) used to not be consistent prior to F# 5. Some edge-case behavior threw an exception and some wouldn&#8217;t. In F# 5, all built-in types now return empty slices for slices that are impossible to generate:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/ce0fedfe32fdc15682998f4c123552fa.js\"><\/script><\/p>\n<h3>Fixed-index slices for 3D and 4D arrays in FSharp.Core<\/h3>\n<p>The built-in 3D and 4D array types have always supported slices, but they did not support fixing a particular index (such as the <code>y<\/code>-dimension in a 3D array). Now they do!<\/p>\n<p>To illustrate this, consider the following 3D array:<\/p>\n<p><em>z = 0<\/em><\/p>\n<table>\n<thead>\n<tr>\n<th>xy<\/th>\n<th>0<\/th>\n<th>1<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>0<\/strong><\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td><strong>1<\/strong><\/td>\n<td>2<\/td>\n<td>3<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><em>z = 1<\/em><\/p>\n<table>\n<thead>\n<tr>\n<th>xy<\/th>\n<th>0<\/th>\n<th>1<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>0<\/strong><\/td>\n<td>4<\/td>\n<td>5<\/td>\n<\/tr>\n<tr>\n<td><strong>1<\/strong><\/td>\n<td>6<\/td>\n<td>7<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>What if you wanted to extract the slice <code>[| 4; 5 |]<\/code> from the array? This is now very simple!<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/bafe4eef54fc8ae664b90ad3240928ed.js\"><\/script><\/p>\n<p>This kind of slice used to not be possible prior to F# 5.<\/p>\n<h2>F# quotations improvements<\/h2>\n<p>We\u2019re finishing up a fundamental improvement to F# Code Quotations, a metaprogramming feature that lets you generate and manipulate an abstract syntax tree that represents the F# code.<\/p>\n<p>Although powerful, F# Code Quotations have had a severe deficiency up until this point: they didn\u2019t carry \u201ctrait calls\u201d to sufficiently represent the actual semantics of the code being \u201cquoted\u201d if it relied on type constraints. A common way this could manifest itself was \u201callowing\u201d code with arithmetic that would merely throw an exception at runtime.<\/p>\n<p>These enhancements are particularly relevant to translating F# code to run on other runtimes like PyTorch or ONNX, a key scenario we\u2019re exploring as a means to attract developers in more \u201canalytical\u201d domains to F# and .NET. We also anticipate numerous smaller issues that F# developers using F# Code Quotations today had to work around to be resolved, with the code they expect to \u201cjust work\u201d actually live up to that phrase.<\/p>\n<p>A trivial example of code that now just works is as follows:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/86a805c4858a908a2c492ea920fd3555.js\"><\/script><\/p>\n<p>This used to throw an exception. It now emits -1 as you would expect it to.<\/p>\n<h2>Applicative Computation Expressions<\/h2>\n<p>Computation expressions (CEs) are used today to model \u201ccontextual computations\u201d, or in more functional programming friendly terminology, monadic computations. However, they are a more flexible construct than just offering syntax for monads (you can encode monoids or even a computation expression that <a href=\"http:\/\/www.fssnip.net\/qR\/title\/A-bindreturn-computation-expression-that-does-not-satisfy-any-of-the-monad-laws\">explicitly violates every monad law if you like<\/a>).<\/p>\n<p>F# 5 introduces applicative CEs, which are a slightly different form of CE than what you\u2019re perhaps used to. Applicative CEs allow for significantly more efficient computations provided that every computation is independent, and their results are merely accumulated at the end. When computations are independent of one another, they are also trivially parallelizable. This benefit comes at a restriction, though: computations that depend on previously-computed values are not allowed.<\/p>\n<p>The follow example shows a basic applicative CE for the <code>Result<\/code> type.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/8540e3fb1edf647f3c7ee8e4352c5941.js\"><\/script><\/p>\n<p>Work for Applicative CEs was done in collaboration with <a href=\"https:\/\/www.gresearch.co.uk\/\">G-Research<\/a>, who frequently contribute to the F# ecosystem. Thanks, folks!<\/p>\n<p>If you\u2019re a library author who exposes CEs in their library today, there are some additional considerations you\u2019ll need to be aware of. These will be documented in the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/language-reference\/computation-expressions\">Computation Expressions<\/a> article by release.<\/p>\n<p>For consumers of applicative CEs, things aren\u2019t too different from the CEs that you already use. The previously-mentioned restriction around independent computations is the key concept to understand.<\/p>\n<h2>Improved stack traces in F# async and other computation expressions<\/h2>\n<p>Thanks to a contribution by <a href=\"https:\/\/github.com\/NinoFloris\">Nino Floris<\/a>, stack traces coming from caught exceptions in computation expressions (such as F# async) now retain more information. Consider the following code that uses the <a href=\"https:\/\/www.nuget.org\/packages\/Ply\/\">Ply<\/a> library:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/3c21f2a05876e4dc16778fa18a8c8a11.js\"><\/script><\/p>\n<p>Prior to F# 5, the <code>origin<\/code> function would not appear in stack traces without a workaround in the Ply library (and any other library where this is a scenario). Now it shows the full trace:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/4147b1ceefd84c67c55cc17f6a199784.js\"><\/script><\/p>\n<h2>Improved .NET interop<\/h2>\n<p>F# 5 features several improvements to .NET interop.<\/p>\n<h3>Interfaces can be implemented at different generic instantiations<\/h3>\n<p>You can now implement the same interface at different generic instantiations. <a href=\"https:\/\/github.com\/0x53A\">Lukas Rieger<\/a> contributed an initial design and implementation of this feature.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/d25aede7921a36e88ee46b9b11386b4a.js\"><\/script><\/p>\n<h3>Default interface member consumption<\/h3>\n<p>F# 5 lets you consume <a href=\"https:\/\/docs.microsoft.com\/dotnet\/csharp\/whats-new\/csharp-8#default-interface-methods\">interfaces with default implementations<\/a>.<\/p>\n<p>Consider an interface defined in C# like this:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/f18e9e91d23ac32c0bcf13f82f8888e2.js\"><\/script><\/p>\n<p>You can consume it in F# through any of the standard means of implementing an interface:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/6a9eddd1fcb4f117baa93710fc9e7400.js\"><\/script><\/p>\n<p>This lets you safely take advantage of C# code and .NET components written in modern C# when they expect users to be able to consume a default implementation.<\/p>\n<h3>Better interop with nullable value types<\/h3>\n<p><a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.nullable-1\">Nullable (value) types<\/a> (called Nullable Types historically) have long been supported by F#, but interacting with them has traditionally been somewhat of a pain since you&#8217;d have to construct a <code>Nullable<\/code> or <code>Nullable&lt;SomeType&gt;<\/code> wrapper every time you wanted to pass a value. Now the compiler will implicitly convert a value type into a <code>Nullable&lt;ThatValueType&gt;<\/code> if the target type matches. The following code is now possible:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/a0603f0e6da3693b2f243eabfbd977c7.js\"><\/script><\/p>\n<h2>Improved runtime performance<\/h2>\n<p>.NET 5 brings improvements to the performance of processing <code>.tail<\/code> calls, which F# emits in various scenarios (especially in recursive and async code). The impact of this on the runtime performance of your app can vary depending on the <em>kind<\/em> of code you&#8217;re writing, as not all <code>.tail<\/code> calls are equal. However, you should generally expect an improvement to runtime performance compared to .NET Core 3.1.<\/p>\n<h2>Improved Map and Set performance in FSharp.Core<\/h2>\n<p>The runtime performance of the <code>Map<\/code> and <code>Set<\/code> data structure has improved considerably thanks to work by <a href=\"https:\/\/github.com\/buybackoff\" target=\"_blank\" rel=\"noopener noreferrer\">Victor Baybekov<\/a>.<\/p>\n<p>For <code>Map<\/code>, the improved operations are:<\/p>\n<ul>\n<li>Retrieval via index &#8211; up to 50% faster<\/li>\n<li><code>containsKey<\/code> &#8211; up to 50% faster<\/li>\n<li><code>count<\/code> &#8211; up to 50% faster<\/li>\n<li><code>iter<\/code> &#8211; up to 15% faster<\/li>\n<li><code>add<\/code> &#8211; up to 40% faster<\/li>\n<li><code>remove<\/code> &#8211; up to 33% faster<\/li>\n<\/ul>\n<p>For <code>Set<\/code>, the improved operations are:<\/p>\n<ul>\n<li><code>containsKey<\/code> &#8211; up to 40% faster<\/li>\n<li><code>isSubsetOf<\/code> &#8211; up to 40% faster<\/li>\n<li><code>max<\/code> &#8211; up to 50% faster<\/li>\n<li><code>count<\/code> &#8211; up to 50% faster<\/li>\n<li><code>add<\/code> &#8211; up to 30% faster<\/li>\n<li><code>remove<\/code> &#8211; up to 15% faster<\/li>\n<\/ul>\n<p>Memory usage for each operation is also slightly improved. Thanks, Viktor!<\/p>\n<h2>Improved compiler performance<\/h2>\n<p>F# 5 brings along some performance improvements for the compiler and editor tooling.<\/p>\n<p>F# compiler performance has steadily improved over the years. I&#8217;ll demostrate this by compiling the core project in the <a href=\"https:\/\/github.com\/fsprojects\/FSharpPlus\">FSharpPlus<\/a> library. This core project makes use of a lot of F# constructs in a way that acts as a great stress test for the compiler itself. I ran the following commands against F# 5, F# 4.7, and F# 4.5.<\/p>\n<pre><code class=\"console\">dotnet clean\r\ndotnet msbuild \/m:1 \/clp:PerformanceSummary\r\n<\/code><\/pre>\n<p>These commands clean the output directories and force msbuild to run serially (though it would likely be serial anyways since it&#8217;s compiling a single project), and reports timings for all tasks run during build. The following table shows the time it took for the <code>Fsc<\/code> task to complete, which is the F# compiler:<\/p>\n<table>\n<thead>\n<tr>\n<th>F# version<\/th>\n<th>Time to compile (second, rounded)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>F# 5<\/td>\n<td>49 seconds<\/td>\n<\/tr>\n<tr>\n<td>F# 4.7<\/td>\n<td>68 seconds<\/td>\n<\/tr>\n<tr>\n<td>F# 4.5<\/td>\n<td>101 seconds<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There was a big improvement from F# 4.5 to F# 4.7, and another big jump with F# 5 as well!<\/p>\n<p>Your own results may vary a bit depending on a variety of factors, but if you try this out yourself you should see a fairly similar spread. It&#8217;s also worth noting that everything else in the .NET toolchain has improved too, so it&#8217;s not just the F# compiler getting faster when you use F# 5 with .NET 5.<\/p>\n<h2>Improved compiler analysis for library authors<\/h2>\n<p>F# 5 also includes a compiler feature that checks XML documentation against the signatures they document if you opt into it. This can be turned on in a project file via the <code>OtherFlags<\/code> property:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/dda36db07d9b62f53e98e9a672c50a25.js\"><\/script><\/p>\n<p>This will warn when the following code is compiled because the name of the parameter in the XML documentation doesn&#8217;t match the name of the parameter in source.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/59813f0d1f93174f1dccc6afee8b7939.js\"><\/script><\/p>\n<p>This is a helpful setting for library authors who want to ensure coherence between their libraries and documentation.<\/p>\n<h2>Preview features<\/h2>\n<p>F# 5 is also bringing along two new preview features. To use these, you&#8217;ll need to set your <code>&lt;LangVersion&gt;preview&lt;\/LangVersion&gt;<\/code> like so:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/3a12e552cc64918d697c430c7b5cfcf7.js\"><\/script><\/p>\n<h3>Preview: reverse indexes<\/h3>\n<p>We decided to keep the ability to do reverse indexes in preview for F# 5. There are still some quirks to work out with respect to <code>System.Range<\/code> and <code>System.Index<\/code> interop that we want to get right before releaseing fully.<\/p>\n<p>The syntax is <code>^idx<\/code>. Here\u2019s how you can an element 1 value from the end of a list:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/e706d75e3077b59e0f177f358f628af8.js\"><\/script><\/p>\n<p>You can also define reverse indexes for your own types. To do so, you\u2019ll need to implement the following method:<\/p>\n<pre><code class=\"fsharp\">GetReverseIndex: dimension: int -&gt; offset: int\r\n<\/code><\/pre>\n<p>Here\u2019s an example for the <code>Span&lt;'T&gt;<\/code> type:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/d0abbcf3e1140126bf8dd0a3ddb36a95.js\"><\/script><\/p>\n<p>We feel that these three enhancements will make slicing data types more convenient in F# moving forward. What do you think?<\/p>\n<h3>Preview: overloads of custom keywords in computation expressions<\/h3>\n<p>Computation expressions are a powerful feature for library and framework authors. They allow you to greatly improve the expressiveness of your components by letting you define well-known members and form a DSL for the domain you&#8217;re working in.<\/p>\n<p><a href=\"https:\/\/github.com\/Nhowka\">Diego Esmerio<\/a> and <a href=\"https:\/\/github.com\/panesofglass\">Ryan Riley<\/a> contributed a design an implementation to allow for overloading custom keywords in computation expressions. This new feature allows code like the following to be written:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/802d640dd1188100a30da93137d4fc6b.js\"><\/script><\/p>\n<p>Prior to this change, you could write the <code>InputBuilder<\/code> type as it is, but you couldn&#8217;t use it the way it&#8217;s used in the previous example. Since overloads, optional parameters, and now <code>System.ParamArray<\/code> types are allowed, everything just works as you&#8217;d expect it to.<\/p>\n<h2>What&#8217;s next<\/h2>\n<p>Now that F# 5 is released, we&#8217;re moving our focus to a few areas:<\/p>\n<ol>\n<li>Improving our OSS infrastructure<\/li>\n<li>Core F# tooling improvements<\/li>\n<li>Planning for the next F# version<\/li>\n<\/ol>\n<p>Today, the <a href=\"https:\/\/github.com\/dotnet\/fsharp\">F# development repository<\/a> is quite a complex codebase. There are several test suites that were created at various points in history, one of which being particularly challenging to work with because it doesn&#8217;t load in any IDE tooling. We feel that it&#8217;s unfair to ask open source contributors to do things like add or update tests when this test suite is concerned, so we&#8217;re migrating it to be modern. The codebase also builds two versions of the F# compiler, called the &#8220;desktop compiler&#8221; and the &#8220;CoreCLR compiler&#8221;. From a technical standpoint, the &#8220;CoreCLR compiler&#8221; can be used to build any F# project targeting any .NET flavor on any OS. The only reason why we still build both is technical debt that we intend on paying off. From an open source contributor&#8217;s standpoint, this should simplify things as well.<\/p>\n<p>We also plan on making significant F# tooling improvements over time. We&#8217;ve already started this work. One of the first steps was to incorporate <a href=\"https:\/\/www.nuget.org\/packages\/FSharp.Compiler.Service\/\">FSharp.Compiler.Service<\/a> into our build and packaging infrastructure so that any consumers of this package (e.g., the <a href=\"https:\/\/github.com\/ionide\/ionide-vscode-fsharp\">Ionide plugin in VSCode<\/a>) can simply add a NuGet feed and get nightly updates. Next, we&#8217;ll work towards retiring the <code>FSharp.Compiler.Private<\/code> project, which is functionally equivalent to <code>FSharp.Compiler.Service<\/code>, so that all F# tooling consumes the same functionality in the same way. From there, we intend on working with the F# community to eventually harden the <a href=\"https:\/\/github.com\/fsharp\/FsAutoComplete\/\">F# LSP implementation<\/a> so that it powers all F# editor tooling (including Visual Studio). The long-term goal is that all F# tools have consistent behavior and feature availability, with individual editors adding their own &#8220;flavor&#8221; and unique feature set on top of that behavior so that F# programmers can pick the tool they like the most.<\/p>\n<p>Additionally, we&#8217;re continuing to invest in F# tooling for Visual Studio by improving performance and adding several features. One such feature is called &#8220;Inline Hints&#8221;, which you can activate by pressing and holding a key command. This lets you see the inferred types for all declarations and the names of F# parameters when applied (as if they were named parameters):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2020\/11\/fs-inline-hints.png\" alt=\"F# inline hints\" \/><\/p>\n<p>The intention behind a feature like this is to let you effectively ask the compiler what it&#8217;s chosen to infer for your code at any time. We&#8217;re interested in incorporating other features that make things more productive for F# developers.<\/p>\n<p>Finally, we&#8217;re planning the next version of the F# language. There are several things on the docket already:<\/p>\n<ol>\n<li>Finishing reverse indices to account for .NET <code>Range<\/code> and <code>Index<\/code> interop<\/li>\n<li>Finishing overloads for custom computation expressions<\/li>\n<li>Adding support for a <code>task { }<\/code> computation expression with state machine generation<\/li>\n<li>Enhancements to the F# type system to better support efforts like <a href=\"https:\/\/diffsharp.github.io\/\">DiffSharp<\/a><\/li>\n<\/ol>\n<p>The list for new F# language features is constantly evolving and new requirements come in and we adjust accordingly. However, we&#8217;re still committed to the direction that we set out on with F# 5. We want to continue to make F# a delightful language for interactive and analytical programming. You can expect to see more goodness in the near future.<\/p>\n<p>Cheers, and happy F# coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>F# 5 is the latest version of F#, the functional programming language for .NET. F# 5 is focused on making interactive and analytical programming a joy by revamping F# Interactive and adding support for Jupyter Notebooks and VSCode Notebooks. It also includes some highly-requested language features like string interpolations and nameof.<\/p>\n","protected":false},"author":678,"featured_media":30568,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[],"class_list":["post-30567","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"acf":[],"blog_post_summary":"<p>F# 5 is the latest version of F#, the functional programming language for .NET. F# 5 is focused on making interactive and analytical programming a joy by revamping F# Interactive and adding support for Jupyter Notebooks and VSCode Notebooks. It also includes some highly-requested language features like string interpolations and nameof.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/30567","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/678"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=30567"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/30567\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/30568"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=30567"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=30567"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=30567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}