{"id":18599,"date":"2018-07-26T12:22:31","date_gmt":"2018-07-26T19:22:31","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/dotnet\/?p=18495"},"modified":"2020-04-09T03:14:06","modified_gmt":"2020-04-09T10:14:06","slug":"announcing-f-4-5-preview","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-f-4-5-preview\/","title":{"rendered":"Announcing F# 4.5 Preview"},"content":{"rendered":"<p>We\u2019re very excited to announce that we\u2019ll be shipping a new language version of F# soon. The version will be F# 4.5.<\/p>\n<p>F# 4.5 has been developed entirely via an open RFC (requests for comments) process, with significant contributions from the community, especially in feature discussions and demonstrating use cases. You can view all RFCs that correspond with this release:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/fsharp\/fslang-design\/tree\/master\/FSharp-4.5\">F# 4.5 RFCs<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/fsharp\/fslang-design\/tree\/master\/FSharp.Core-4.5.0.0\">FSharp.Core 4.5.0 RFCs<\/a><\/li>\n<\/ul>\n<p>This post will talk a little bit about some of the features in this new language version.<\/p>\n<h2>Get started<\/h2>\n<p>First, install:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/cli\/tree\/release\/2.1.4xx#installers-and-binaries\">A preview of the .NET SDK 2.1.400<\/a> to ensure you have the latest bits for for F# in .NET Core<\/li>\n<li><a href=\"https:\/\/visualstudio.microsoft.com\/vs\/preview\/\">Visual Studio 2017 update 15.8 Preview 5<\/a> if you are on Windows<\/li>\n<\/ul>\n<p>If you create a .NET desktop F# project in Visual Studio (from the F# desktop development component), then you will need to update your FSharp.Core package to 4.5.2 with the NuGet UI.<\/p>\n<p>Once you have installed the necessary bits, you can start developing F# 4.5 code with <a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/get-started\/get-started-visual-studio\">Visual Studio<\/a>, <a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/get-started\/get-started-with-visual-studio-for-mac\">Visual Studio for Mac<\/a>, or <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/fsharp\/get-started\/get-started-vscode\">Visual Studio Code with Ionide<\/a>.<\/p>\n<p>When .NET Core SDK 2.1.400 and Visual Studio 2017 version 15.8 are released, the referenced FSharp.Core will be 4.5.2 for all new projects and you will not need to perform this second step.<\/p>\n<h2>Versioning Alignment<\/h2>\n<p>The first thing you may notice about F# 4.5 is that it\u2019s higher than F# 4.1. But you may not have expected it to be <em>four<\/em> decimal places higher! The following table details this change for F# 4.5:<\/p>\n<table style=\"width: 100%;\">\n<tbody>\n<tr>\n<td><\/td>\n<td>F# language version<\/td>\n<td>FSharp.Core binary version<\/td>\n<td><a href=\"https:\/\/www.nuget.org\/packages\/FSharp.Core\/\" target=\"_blank\" rel=\"noopener noreferrer\">FSharp.Core NuGet package<\/a><\/td>\n<\/tr>\n<tr>\n<td><strong>Old World<\/strong><\/td>\n<td>F# 4.1<\/td>\n<td>4.4.1.0<\/td>\n<td>4.x.y, where x &gt;= 2 for .NET Standard support<\/td>\n<\/tr>\n<tr>\n<td><strong>New World<\/strong><\/td>\n<td>F# 4.5<\/td>\n<td>4.5.x.0<\/td>\n<td>4.5 x<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There is a good reason for this change. As you can see, prior to F# 4.5, each item has a different version! The reasons for this are historical, but the end result is that it has been horribly confusing for F# users for a long time. So, we decided to clear it up.<\/p>\n<p>From here on out, the major and minor versions for these three assets will be synced, as per <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/tooling\/FST-1004-versioning-plan.md\">the RFC we wrote detailing this change<\/a>.<\/p>\n<h2>Side-by-side F# compilers deployed by Visual Studio<\/h2>\n<p>In previous versions of Visual Studio, you may have noticed that the F# Compiler SDK was bumped from 4.1 to 10.1. This is because the F# compiler evolves more rapidly than the language, often to fix bugs or improve performance. In the past, this was effectively ignored, with the compiler SDK still containing the same version number as the language version. This inaccurate representation of artifacts on your machine drove an effort to separate the versioning of the compiler and tools separately from the language they implement. As per the <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/tooling\/FST-1004-versioning-plan.md\">RFC detailing this change<\/a>, the F# compiler and tools will use semantic versioning.<\/p>\n<p>Additionally, the F# compiler SDK used to install as a singleton on your machine. If you had multiple side-by-side Visual Studio 2017 versions installed on your machine, the tools for all installations would pick up the same F# compiler, regardless of if they were ever intended to use that compiler. This means that something like using both release and preview version of Visual Studio could silently opt-in your release build of Visual Studio to use preview bits of F#! This resulted in multiple issues where users were confused about the behavior on their machine.<\/p>\n<p>For F# 4.5, the compiler SDK version will be 10.2. When installed with Visual Studio, this will be fully side-by-side with that version of Visual Studio. Additional Visual Studio installations will not pick this higher compiler SDK version.<\/p>\n<h4>Accounting for this change on Windows build servers:<\/h4>\n<p>You may be doing one of the following things to install F# on a Windows build server:<\/p>\n<ul>\n<li>Installing the full Visual Studio IDE<\/li>\n<li>Installing the F# Compiler SDK MSI<\/li>\n<\/ul>\n<p>Neither of these options have been recommended for some time, but are still available with F# 4.1.<\/p>\n<p>For using F# 4.5 in a Windows build server, we recommend (in order of preference), Using the <a href=\"https:\/\/www.microsoft.com\/net\/download\/windows\">.NET SDK<\/a>, the <a href=\"https:\/\/www.nuget.org\/packages\/FSharp.Compiler.Tools\/\">FSharp.Compiler.Tools package<\/a>, or the <a href=\"https:\/\/visualstudio.microsoft.com\/downloads\/\">Visual Studio Build Tools SKU<\/a>. This change will be documented in the official F# docs and the F# Software Foundation guides page by the time F# 4.5 is out of preview.<\/p>\n<h2>Span support<\/h2>\n<p>The largest piece of F# 4.5 is a feature set aligned with the new <a href=\"https:\/\/msdn.microsoft.com\/en-us\/magazine\/mt814808.aspx\/\">Span feature in .NET Core 2.1<\/a>. The F# feature set is comprised of:<\/p>\n<ul>\n<li>The <code>voidptr<\/code> type.<\/li>\n<li>The <code>NativePtr.ofVoidPtr<\/code> and <code>NativePtr.toVoidPtr<\/code> functions in FSharp.Core.<\/li>\n<li>The <code>inref&lt;'T&gt;<\/code> and <code>outref&lt;'T&gt;<\/code>types, which are readonly and write-only versions of <code>byref&lt;'T&gt;<\/code>, respectively.<\/li>\n<li>The ability to produce <code>IsByRefLike<\/code> structs (examples of such structs: <code>Span&lt;'T&gt;<\/code>and <code>ReadOnlySpan&lt;'T&gt;<\/code>).<\/li>\n<li>The ability to produce <code>IsReadOnly<\/code> structs.<\/li>\n<li>Implicit de-reference of <code>byref&lt;'T&gt;<\/code> and <code>inref&lt;'T&gt;<\/code> returns from functions and methods.<\/li>\n<li>The ability to write extension methods on <code>byref&lt;'T&gt;<\/code>, <code>inref&lt;'T&gt;<\/code>, and <code>outref&lt;'T&gt;<\/code>(note: not optional type extensions).<\/li>\n<li>Comprehensive safety checks to prevent unsoundness in your code.<\/li>\n<\/ul>\n<p>The main goals for this feature set are:<\/p>\n<ul>\n<li>Offer ways to interoperate with and product high-performance code in F#.<\/li>\n<li>Full parity with .NET Core performance innovations.<\/li>\n<li>Better code generation, especially for byref-like constructs.<\/li>\n<\/ul>\n<p>What this boils down into is a feature set that allows for safe use of performance-oriented constructs in a very restrictive manner. When programming with these features, you will find that they are far more restrictive than you might initially anticipate. For example, you cannot define an F# record type that has a Span inside of it. This is because a Span is a &#8220;byref-like&#8221; type, and byref-like types can only contained in other byref-like types. Allowing such a thing would result in unsound F# code that would fail at runtime! Because of this, we implement strict safety checks in the F# compiler to prevent you from writing code that is unsound.<\/p>\n<p>If you\u2019ve been following along with the <code>Span&lt;'T&gt;<\/code> and <code>ref<\/code> work in C# 7.3, a rough syntax guide is as follows:<\/p>\n<table style=\"width: 100%; height: 156px;\">\n<tbody>\n<tr style=\"height: 26px;\">\n<th style=\"height: 26px;\">C#<\/th>\n<th style=\"height: 26px;\">F#<\/th>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"height: 26px;\"><code>out int arg<\/code><\/td>\n<td style=\"height: 26px;\"><code>arg: byref&lt;int&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"height: 26px;\"><code>out int arg<\/code><\/td>\n<td style=\"height: 26px;\"><code>arg: outref&lt;int&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"height: 26px;\"><code>in int arg<\/code><\/td>\n<td style=\"height: 26px;\"><code>arg: inref&lt;int&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"height: 26px;\"><code>ref readonly int<\/code><\/td>\n<td style=\"height: 26px;\"><em>Inferred <\/em>or <code>arg: inref&lt;int&gt;<\/code><\/td>\n<\/tr>\n<tr style=\"height: 26px;\">\n<td style=\"height: 26px;\"><code>ref expr<\/code><\/td>\n<td style=\"height: 26px;\"><code>&amp;expr<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The following sample shows a few ways you can use <code>Span&lt;'T&gt;<\/code> with F#:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/278daa5b18abbbb64b779e5e0101ee8e.js\"><\/script><\/p>\n<h3>Safety rules for byrefs<\/h3>\n<p>As previously mentioned, <code>byref<\/code>s and <code>byref<\/code>-like structs are quite restrictive in how they can be used. This is because the goal of this feature set is to make low-level code in the style of pointer manipulation safe and predictable. Doing so is only possible by restricting usage of certain types to appropriate contexts and performing scope analysis on your code to ensure soundness.<\/p>\n<p>A quick summary of some of the safety rules:<\/p>\n<ul>\n<li>A <code>let<\/code>-bound value cannot have its reference escape the scope it was defined in.<\/li>\n<li><code>byref<\/code>-like structs cannot be instance or static members of a class or normal struct.<\/li>\n<li><code>byref<\/code>-like structs cannot by captured by any closure construct.<\/li>\n<li><code>byref<\/code>-like structs cannot be used as a generic type parameter.<\/li>\n<\/ul>\n<p>As a reminder, <code>Span&lt;'T&gt;<\/code> and <code>ReadOnlySpan&lt;'T&gt;<\/code> are <code>byref<\/code>-like structs and are subject to these rules.<\/p>\n<h3>Bug fixes that are not backwards compatible<\/h3>\n<p>There are two bugs fixes as a part of this feature set that are not backwards compatible with F# 4.1 code that deals with consuming C# 7.x ref returns and performs &#8220;evil struct replacement&#8221;.<\/p>\n<h4>Implicit dereference of byref-like return values<\/h4>\n<p>F# 4.1 introduced the ability for F# to <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/FSharp-4.1\/FS-1020-byref-returns.md\">consume byref returns<\/a>. This was done strictly for interoperation with C# <code>ref<\/code> returns, and F# could not produce such a return from F# constructs.<\/p>\n<p>However, in F# 4.1, these values were not implicitly dereferenced in F# code, unlike how they were in equivalent C#. This meant that if you attempted to translate C# code that consumed a <code>ref<\/code> return into equivalent F#, you&#8217;d find that the type you got back from the call was a pointer rather than a value.<\/p>\n<p>Starting with F# 4.5, this value is now implicitly dereferenced in F# code. In addition to bringing this feature set in line with C# behavior, this allows for assignment to <code>byref<\/code> returns from F# functions, methods, and properties as one would expect if they had learned about this feature with C# 7 and higher.<\/p>\n<p>To avoid the implicit dereference, simply apply the <code>&amp;<\/code> operator to the value to make it a <code>byref<\/code>.<\/p>\n<h4>Disabling evil struct replacement on immutable structs<\/h4>\n<p>F# 4.1 (and lower) had a bug in the language where an immutable struct could define a method that completely replaced itself when called. This so-called &#8220;evil struct replacement&#8221; behavior is considered a bug now that F# has a way to represent <code>ReadOnly<\/code> structs. The <code>this<\/code> pointer on a struct will now be an <code>inref&lt;MyStruct&gt;<\/code>, and an attempt to modify the <code>this<\/code> pointer will now emit an error.<\/p>\n<p>You can learn more about the full design and behavior of this feature set <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/FSharp-4.5\/FS-1053-span.md\">in the RFC<\/a>.<\/p>\n<h2>New keyword: match!<\/h2>\n<p><a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/language-reference\/computation-expressions\">Computation Expressions<\/a> now support the `match!` keyword, shortening somewhat common boilerplate existing in lots of code today.<\/p>\n<p>This F# 4.1 code:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/7ae05e6a47c4c15b75d4cabf5151b9ed.js\"><\/script><\/p>\n<p>Can now be written with <code>match!<\/code> in F# 4.5:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/d7dc75d257d5a3388ed5890ee5be6844.js\"><\/script><\/p>\n<p>This feature was contributed entirely by <a href=\"https:\/\/github.com\/jwosty\">John Wostenberg<\/a> in the F# OSS community. Thanks, John!<\/p>\n<h2>Relaxed upcast requirements with yield in F# sequence, list and array expressions<\/h2>\n<p>A previous requirement to upcast to a supertype when using <code>yield<\/code> used to be required in F# sequence, list, and array expressions. This restriction was already unnecessary for these expressions since F# 3.1 when not using <code>yield<\/code>, so this makes things more consistent with existing behavior.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/c2e9c07893bb1e1b4027bcf68087548f.js\"><\/script><\/p>\n<h2>Relaxed indentation rules for list and array expressions<\/h2>\n<p>Since F# 2.0, expressions delimited by &#8216;}&#8217; as an ending token would allow \u201cundentation\u201d. However, this was not extended to array and list expressions, thus resulting in confusing warnings for code like this:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/05a92000a7a2277dd8c9a78501614788.js\"><\/script><\/p>\n<p>The solution would be to insert a new line for the named argument and indent it one scope, which is unintuitive. This has now been relaxed, and the confusing warning is no more. This is especially helpful when doing reactive UI programming with a library such as <a href=\"https:\/\/elmish.github.io\/elmish\/\">Elmish<\/a>.<\/p>\n<h2>F# enumeration cases emitted as public<\/h2>\n<p>To help with profiling tools, we now emit F# enumeration cases as public under all circumstances. This makes it easier to analyze the results of running performance tools on F# code, where the label name holds more semantic information than the backing integer value. This is also aligned with how C# emits enumerations.<\/p>\n<h2>Better async stack traces<\/h2>\n<p>Starting with F# 4.5 and FSharp.Core 4.5.0, stack traces for async computation expressions:<\/p>\n<ul>\n<li>Reported line numbers now correspond to the failing user code<\/li>\n<li>Non-user code is no longer emitted<\/li>\n<\/ul>\n<p>For example, consider the following DSL and its usage with an FSharp.Core version prior to 4.5.0:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/41e204506e273b45942225b20e422c1e.js\"><\/script><\/p>\n<p>Note that both the <code>f1<\/code> and <code>f2<\/code> functions are called twice. When you look at the result of this in F# Interactive, you\u2019ll notice that stack traces will never list names or line numbers that refer to the actual invocation of these functions! Instead, they will refer to the closures that perform the call:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/50c554dd4a0e1fce45d5fca5dbdc80eb.js\"><\/script><\/p>\n<p>This was confusing in F# async code prior to F# 4.5, which made diagnosing problems with async code difficult in large codebases.<\/p>\n<p>With FSharp.Core 4.5.0, we <a href=\"https:\/\/github.com\/Microsoft\/visualfsharp\/blob\/master\/src\/fsharp\/FSharp.Core\/async.fs#L1092\">selectively inline certain members<\/a> so that the closures become part of user code, while also selectively hiding certain implementation details in relevant parts of FSharp.Core from the debugger so that they don\u2019t accidentally muddy up stack traces.<\/p>\n<p>The result is that names and line numbers that correspond to actual user code will now be present in stack traces.<\/p>\n<p>To demonstrate this, we can apply this technique (with some additional modifications) to the previously-mentioned DSL:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/53d19a3dff170d7276c77de13ac1e795.js\"><\/script><\/p>\n<p>When ran again in F# Interactive, the printed stack trace now shows names and line numbers that correspond to user calls to functions, not the underlying closures:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/f5b3e5a5c6404089f10fed7b07dcce05.js\"><\/script><\/p>\n<p>As mentioned in the <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/FSharp.Core-4.5.0.0\/FS-1059-improve-async-stack-traces.md\">RFC for this feature<\/a>, there are other problems inherent to the space, and other solutions that may be pursued in a future F# version.<\/p>\n<h2>Additional FSharp.Core improvements<\/h2>\n<p>In addition to the improved Async stack traces, there were a small number of improvements to FSharp.Core.<\/p>\n<ul>\n<li><code>Map.TryGetValue<\/code> (<a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/FSharp.Core-4.5.0.0\/FS-1050-trygetvalue-map.md\">RFC<\/a>)<\/li>\n<li><code>ValueOption&lt;'T&gt;<\/code> (<a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/FSharp.Core-4.5.0.0\/FS-1057-valueoption.md\">RFC<\/a>)<\/li>\n<li><code>FuncConvert.FromFunc<\/code> and <code>FuncConvert.FromAction<\/code> APIs to enable accepting <code>Func&lt;\u2019A, \u2018B&gt;<\/code> and <code>Action&lt;\u2019A, \u2018B&gt;<\/code> instances from C# code. (<a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/master\/FSharp.Core-4.5.0.0\/FS-1045-func-to-fsharpfunc-overloads.md\">RFC<\/a>)<\/li>\n<\/ul>\n<p>The following F# code demonstrates the usage of the first two:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/cartermp\/c2e831e4057d250d072c413bfd2c3d24.js\"><\/script><\/p>\n<p>The FuncConvert API additions aren\u2019t that useful for F#-only code, but they do help with C# to F# interoperability, allowing the use of \u201cmodern\u201d C# constructs like <code>Action<\/code> and <code>Func<\/code> to convert into F# functions.<\/p>\n<h2>The road to official release<\/h2>\n<p>This preview is very, very stable. In fact, after extensive testing, we feel that it\u2019s stable enough for us to consider it a proper release, but due to the timing of the .NET SDK and Visual Studio releases, we\u2019re releasing it now as a preview. Soon, when Visual Studio 2017 update 15.8 and the corresponding .NET Core 2.1 SDK update release, we will declare F# 4.5 as fully released and it will be fully included in both places.<\/p>\n<p>Cheers, and happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Accounting for this change on Windows build servers: You may be doing one of the following things to install F# on a Windows build server. Installing the full Visual Studio IDE Installing the F# Compiler SDK MSI Neither of these options have been recommended for some time, but are still available with F# 4.1. <\/p>\n","protected":false},"author":678,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196,636],"tags":[],"class_list":["post-18599","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core","category-fsharp"],"acf":[],"blog_post_summary":"<p>Accounting for this change on Windows build servers: You may be doing one of the following things to install F# on a Windows build server. Installing the full Visual Studio IDE Installing the F# Compiler SDK MSI Neither of these options have been recommended for some time, but are still available with F# 4.1. <\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/18599","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=18599"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/18599\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=18599"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=18599"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=18599"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}