{"id":36112,"date":"2021-10-19T11:00:09","date_gmt":"2021-10-19T18:00:09","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=36112"},"modified":"2021-11-09T13:56:35","modified_gmt":"2021-11-09T20:56:35","slug":"whats-new-in-fsharp-6","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/whats-new-in-fsharp-6\/","title":{"rendered":"What\u2019s new in F# 6"},"content":{"rendered":"<p>We\u2019re excited to announce the availability F# 6, shipping with .NET 6 RC2 and Visual Studio 2022 RC2. It&#8217;s the next step to making it easier for you to write robust, succinct and performant code. You can get F# 6 in the following ways:<\/p>\n<ul>\n<li><a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet\/6.0\">Install the latest .NET 6 SDK RC2 preview<\/a><\/li>\n<li><a href=\"https:\/\/visualstudio.microsoft.com\/vs\/preview\/\">Install Visual Studio 2022 RC2 preview<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/interactive#notebooks-with-net\">Use .NET Interactive Notebooks in Jupyter or VS Code<\/a><\/li>\n<\/ul>\n<p>F# 6 is about making F# simpler and more performant. This applies to the language design, library, and tooling. A major goal of long-term language evolution is to remove corner-cases in the language that surprise users or are unnecessary hurdles on the path to adoption. We are very pleased to have worked with the F# community in this release to make the F# language simpler, more performant, and easier to learn.<\/p>\n<p>To learn more about F#, see <a href=\"https:\/\/channel9.msdn.com\/Events\/dotnetConf\/Focus-on-FSharp\">The .NET Conf Focus Day on F#<\/a> including the <a href=\"https:\/\/channel9.msdn.com\/Events\/dotnetConf\/Focus-on-FSharp\/Don-Symes-F-Bonanza\">F# Bonanza<\/a>, <a href=\"https:\/\/channel9.msdn.com\/Events\/dotnetConf\/Focus-on-FSharp\/Don-Teaches-Guido-FSharp\">Guido van Rossum Learns F#<\/a> and <a href=\"https:\/\/channel9.msdn.com\/Events\/dotnetConf\/Focus-on-FSharp\/Starting-Your-FSharp-Journey\">Starting Your F# Journey<\/a>.<\/p>\n<h2>Making F# faster and more interopable with task {\u2026}<\/h2>\n<p>One of the most requested features for F# &#8211; and the most significant technical feature in this release \u2013 has been to make authoring asynchronous tasks simpler, more performant and more interoperable with other .NET languages like C#. Previously, creating .NET tasks required using <code>async {\u2026}<\/code> to create a task and then invoking it with <code>Async.AwaitTask<\/code>. With F# 6 you can now use <code>task {\u2026}<\/code> directly to create the task and await it. For example, consider the following F# code to create a .NET-compatible task:<\/p>\n<pre><code class=\"language-fsharp\">let readFilesTask (path1, path2) =\r\n   async {\r\n        let! bytes1 = File.ReadAllBytesAsync(path1) |&gt; Async.AwaitTask\r\n        let! bytes2 = File.ReadAllBytesAsync(path2) |&gt; Async.AwaitTask\r\n        return Array.append bytes1 bytes2\r\n   } |&gt; Async.StartAsTask<\/code><\/pre>\n<p>This code can now become:<\/p>\n<pre><code class=\"language-fsharp\">let readFilesTask (path1, path2) =\r\n   task {\r\n        let! bytes1 = File.ReadAllBytesAsync(path1)\r\n        let! bytes2 = File.ReadAllBytesAsync(path2)\r\n        return Array.append bytes1 bytes2\r\n   }<\/code><\/pre>\n<p>The built-in support for <code>task {\u2026}<\/code> is available ubiquitously in F# code \u2013 no namespaces need to be opened.<\/p>\n<p>Task support has previously been available for F# 5.0 through the excellent TaskBuilder.fs and Ply libraries. These guided the design of the support in F# 6 and provided an important source of tests. The authors of these libraries have been major contributors to the design of F# 6, both directly and indirectly. Migrating code to the built-in support should be straightforward. There are however some differences: namespaces and type-inference differ slightly between the built-in support and these libraries, and some additional type annotations may be needed. These community libraries can still be used with F# 6, if explicitly referenced and the correct namespaces opened in each file.<\/p>\n<p>Using <code>task {\u2026}<\/code> is very similar to <code>async {\u2026}<\/code>, and both are supported. Using <code>task {\u2026}<\/code> has several advantages over <code>async {\u2026}<\/code>:<\/p>\n<ul>\n<li>The performance of <code>task {\u2026}<\/code> is much better.<\/li>\n<li>Debugging stepping and stack traces for <code>task {\u2026}<\/code> is better.<\/li>\n<li>Interoperating with .NET packages expecting or producing tasks is easier.<\/li>\n<\/ul>\n<p>If you\u2019re familiar with <code>async {\u2026}<\/code>, there are some differences to be aware of:<\/p>\n<ul>\n<li><code>task {\u2026}<\/code> immediately executes the task to the first asynchronous yield.<\/li>\n<li><code>task {\u2026}<\/code> does not implicitly propagate a cancellation token.<\/li>\n<li><code>task {\u2026}<\/code> does not perform implicit cancellation checks.<\/li>\n<li><code>task {\u2026}<\/code> does not support asynchronous tailcalls. This means using <code>return! ..<\/code> recursively may result in stack overflows if there are no intervening asynchronous yields.<\/li>\n<\/ul>\n<p>In general, you should consider using <code>task {\u2026}<\/code> over <code>async {\u2026}<\/code> in new code if interoperating with .NET libraries that uses tasks. Review code before switching to <code>task {\u2026}<\/code> to ensure you are not relying on the above characteristics of <code>async {\u2026}<\/code>.<\/p>\n<p>The <code>task {\u2026}<\/code> support of F# 6 is built on a foundation called \u201cresumable code\u201d <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/preview\/FS-1087-resumable-code.md\">RFC FS-1087<\/a>. Resumable code is a core technical feature which can be used to build many kinds of high-performance asynchronous and yielding state machines.<\/p>\n<p>In the coming months we will be working with the F# community to utilise this feature to make available two key optional packages:<\/p>\n<ol>\n<li>A fast re-implementation of F# <code>async {\u2026}<\/code> using resumable code.<\/li>\n<li>A fast re-implementation of asynchronous sequences <code>asyncSeq {\u2026}<\/code> using resumable code.<\/li>\n<\/ol>\n<p>Initially these will be delivered via community packages such as FSharp.Control.AsyncSeq. In future versions they may be integrated into FSharp.Core.<\/p>\n<h2>Making F# simpler to learn: indexing with expr[idx]<\/h2>\n<p>In F# 6, we begin <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1110-index-syntax.md\">allowing the syntax <code>expr[idx]<\/code> for indexing syntax<\/a>.<\/p>\n<p>Up to and including F# 5.0, F# has used <code>expr.[idx]<\/code> as indexing syntax. This syntax was based on a similar notation used in OCaml for string indexed lookup. Allowing the use of <code>expr[idx]<\/code> is based on repeated feedback from those learning F# or seeing F# for the first time that the use of dot-notation indexing comes across as an unnecessary divergence from standard industry practice. There is no need for F# to diverge here.<\/p>\n<p>This is not a breaking change \u2013 by default no warnings are emitted on the use of <code>expr.[idx]<\/code>. However, some informational messages are emitted related to this change suggesting code clarifications, and some further informational messages can be optionally activated. For example, an optional informational warning (<code>\/warnon:3566<\/code>) can be activated to start reporting uses of the <code>expr.[idx]<\/code> notation. See <a href=\"https:\/\/aka.ms\/fsharp-index-notation\">Indexer Notation<\/a> for details.<\/p>\n<p>In new code, we recommend the systematic use of <code>expr[idx]<\/code> as the indexing syntax.<\/p>\n<h2>Making F# faster: Struct representations for partial active patterns<\/h2>\n<p>F# includes <a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/language-reference\/active-patterns\">the active patterns<\/a> feature that allows users to extend pattern matching in intuitive and powerful ways. In F# 6 we&#8217;ve augmented that feature with optional <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1039-struct-representation-for-active-patterns.md\">Struct representations for active patterns<\/a>. This allows you to use an attribute to constrain a partial active pattern to return a <a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/language-reference\/value-options\">value option<\/a>:<\/p>\n<pre><code class=\"language-fsharp\">[&lt;return: Struct&gt;]\r\nlet (|Int|_|) str =\r\n   match System.Int32.TryParse(str) with\r\n   | true, int -&gt; ValueSome(int)\r\n   | _ -&gt; ValueNone<\/code><\/pre>\n<p>The use of the attribute is required. At usage sites, code doesn&#8217;t change. The net result is that allocations are reduced.<\/p>\n<h2>Making F# more uniform: overloaded custom operations in computation expressions<\/h2>\n<p>F# 6 activates the feature &#8220;overloaded custom operations in computation expressions&#8221; which has been in preview since F# 5.0. This allows for simpler DSLs in F# including for validation and web programming.<\/p>\n<p>The feature was previously described in <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-f-5\/#preview-overloads-of-custom-keywords-in-computation-expressions\">the announcement for F# 5.0 preview<\/a> and implements <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1056-allow-custom-operation-overloads.md\">F# RFC 1056<\/a>.<\/p>\n<h2>Making F# more uniform: \u201cas\u201d patterns<\/h2>\n<p>In F# 6, the right hand side of an \u201cas\u201d pattern can now itself be a pattern. This is important when a type test has given a stronger type to an input. For example, consider the code<\/p>\n<pre><code class=\"language-fsharp\">type Pair = Pair of int * int\r\n\r\nlet analyzeObject (input: obj) =\r\n    match input with\r\n    | :? (int * int) as (x, y) -&gt; printfn $\"A tuple: {x}, {y}\"\r\n    | :? Pair as Pair (x, y) -&gt; printfn $\"A DU: {x}, {y}\"\r\n    | _ -&gt; printfn \"Nope\"\r\n\r\nlet input = box (1, 2)<\/code><\/pre>\n<p>In each pattern case the input object is type-tested. The right-hand-side of the \u201cas\u201d pattern is now allowed to be a further pattern which can itself match the object at the stronger type.<\/p>\n<h2>Making F# more uniform: Indentation syntax revisions<\/h2>\n<p>The F# community has contributed some key improvements to make the F# language more uniform in F# 6. The most important of these is removing a number of inconsistencies and limitations in F#&#8217;s use of indentation-aware syntax, see <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1108-undentation-frenzy.md\">RFC FS-1108<\/a>. This resolved 10 significant issues highlighted by the F# users since F# 4.0.<\/p>\n<p>For example, in F# 5.0 the following was allowed:<\/p>\n<pre><code class=\"language-fsharp\">let c = (\r\n    printfn \"aaaa\"\r\n    printfn \"bbbb\"\r\n)<\/code><\/pre>\n<p>However the following was not (producing a warning)<\/p>\n<pre><code class=\"language-fsharp\">let c = [\r\n    1\r\n    2\r\n]<\/code><\/pre>\n<p>In F# 6, both are allowed. This makes F# simpler and easier to learn. The F# community contributor <a href=\"https:\/\/github.com\/Happypig375\">Hadrian Tang<\/a> has led the way on this including remarkable and highly valuable systematic testing of the feature.<\/p>\n<h2>Making F# more uniform: Discards on use bindings<\/h2>\n<p>F# 6 allows <code>_<\/code> to be used in a <code>use<\/code> binding, for example:<\/p>\n<pre><code class=\"language-fsharp\">let doSomething () =\r\n    use _ = System.IO.File.OpenText(\"input.txt\")\r\n    printfn \"reading the file\"<\/code><\/pre>\n<p>This feature implements <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1102-discards-on-use-bindings.md\">F# RFC FS-1102<\/a>.<\/p>\n<h2>Making F# more uniform: Formatting for binary numbers<\/h2>\n<p>F# 6 adds the <code>%B<\/code> pattern to the available format specifiers for binary number formats. Consider the following F# code:<\/p>\n<pre><code class=\"language-fsharp\">printf \"%o\" 123\r\nprintf \"%B\" 123<\/code><\/pre>\n<p>This code prints the following output:<\/p>\n<pre><code class=\"language-fsharp\">173\r\n1111011<\/code><\/pre>\n<p>This feature implements <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1100-Printf-binary.md\">F# RFC FS-1100<\/a>.<\/p>\n<h2>Making F# faster: InlineIfLambda<\/h2>\n<p>In F# 6, we&#8217;ve added a new declarative feature that allows code to optionally indicate that lambda arguments should be inlined at callsites.<\/p>\n<p>For example, consider the following <code>iterate<\/code> function to traverse an array:<\/p>\n<pre><code class=\"language-fsharp\">let inline iterateTwice ([&lt;InlineIfLambda&gt;] action) (array: 'T[]) = \r\n    for j = 0 to array.Length-1 do \r\n        action array[j]\r\n    for j = 0 to array.Length-1 do \r\n        action array[j]<\/code><\/pre>\n<p>If the callsite is<\/p>\n<pre><code class=\"language-fsharp\">let arr = [| 1.. 100 |]\r\nlet mutable sum = 0\r\narr  |&gt; iterateTwice (fun x -&gt; \r\n    sum &lt;- sum + x) <\/code><\/pre>\n<p>then after inlining and other optimizations the code becomes:<\/p>\n<pre><code class=\"language-fsharp\">let arr = [| 1.. 100 |]\r\nlet mutable sum = 0\r\nfor j = 0 to array.Length-1 do \r\n    sum &lt;- array[i] + x\r\nfor j = 0 to array.Length-1 do \r\n    sum &lt;- array[i] + x<\/code><\/pre>\n<p>Unlike previous versions of F#, this optimization applies regardless of the size of the lambda expression involved. This feature can also be used to implement loop unrolling and similar transformations reliably.<\/p>\n<p>An opt-in warning (<code>\/warnon:3517<\/code>, off by default) can be turned on to indicate places in your code where <code>InlineIfLambda<\/code> arguments are not bound to lambda expressions at callsites. In normal situations, this warning should not be enabled, however in certain kinds of high-performance programming it can be useful to ensure all code is inlined and flattened.<\/p>\n<h2>Making F# faster: Improved performance and debugging for list and array expressions<\/h2>\n<p>In F# 6, the compiled form of generative list and array expressions is now up to 4x faster (see <a href=\"https:\/\/github.com\/dotnet\/fsharp\/pull\/11592\">the relevant pull request<\/a>). Generative list and array expressions also have greatly improved debugging. For example:<\/p>\n<pre><code class=\"language-fsharp\">let generateList (i: int) =\r\n    [ \"a\"\r\n      \"b\"\r\n      for j in 1 .. 10 do\r\n          \"c\"\r\n          if i % 3 = 0 then \r\n              \"d\"\r\n      \"e\"\r\n    ]<\/code><\/pre>\n<p>This function generates lists of size 13 or 23 depending on the input and now executes more efficiently and breakpoints can be set on the individual lines<\/p>\n<h2>Making F# simpler and more interoperable: Implicit conversions<\/h2>\n<p>In F# 6 we have activated support for additional \u201cimplicit\u201d and \u201ctype-directed\u201d conversions in F#, as described in <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1093-additional-conversions.md\">RFC FS-1093<\/a>.<\/p>\n<p>This change achieves three things.<\/p>\n<ol>\n<li>Fewer explicit upcasts are required<\/li>\n<li>Fewer explicit integer conversions are required<\/li>\n<li>First-class support for .NET-style implicit conversions is added<\/li>\n<\/ol>\n<h3>Additional implicit upcast conversions<\/h3>\n<p>In F# 5.0 and before, upcasts were needed for the return expression when implementing a function where the expressions have different subtypes on different branches, even when a type annotation was present. Consider the following F# 5.0 code (StreamReader derives from TextReader):<\/p>\n<pre><code class=\"language-fsharp\">open System\r\nopen System.IO\r\n\r\nlet findInputSource() : TextReader = \r\n    if DateTime.Now.DayOfWeek = DayOfWeek.Monday then  \r\n        \/\/ On Monday a TextReader\r\n        Console.In\r\n    else\r\n        \/\/ On other days a StreamReader\r\n        File.OpenText(\"path.txt\") :&gt; TextReader<\/code><\/pre>\n<p>Here the branches of the conditional compute a TextReader and StreamReader respectively, and the upcast was added to make both branches have type TextReader. In F# 6, these upcasts are now added automatically. This means the code can now be simpler:<\/p>\n<pre><code class=\"language-fsharp\">let findInputSource() : TextReader = \r\n    if DateTime.Now.DayOfWeek = DayOfWeek.Monday then  \r\n        \/\/ On Monday a TextReader\r\n        Console.In\r\n    else\r\n        \/\/ On other days a StreamReader\r\n        File.OpenText(\"path.txt\")<\/code><\/pre>\n<p>You may optionally enable the warning <code>\/warnon:3388<\/code> to show a warning at every point an additional implicit upcast is used, as described below.<\/p>\n<h3>Implicit integer conversions<\/h3>\n<p>Type-directed conversions also allow for automatically widening 32-bit integers to 64-bit integers more often. For example, the use of 64-bit integers is now ubiquitous in machine-learning libraries. Consider a typical API shape:<\/p>\n<pre><code class=\"language-fsharp\">type Tensor(\u2026) =\r\n    static member Create(sizes: seq&lt;int64&gt;) = Tensor(\u2026)\r\n<\/code><\/pre>\n<p>In F# 5.0, integer literals for int64 must be used:<\/p>\n<pre><code class=\"language-fsharp\">Tensor.Create([100L; 10L; 10L])<\/code><\/pre>\n<p>or<\/p>\n<pre><code class=\"language-fsharp\">Tensor.Create([int64 100; int64 10; int64 10])<\/code><\/pre>\n<p>In F# 6, widening happens automatically for <code>int32<\/code> to <code>int64<\/code>, <code>int32<\/code> to <code>nativeint<\/code> and <code>int32<\/code> to <code>double<\/code>, when both source and destination type are known during type inference, so in cases such as the above <code>int32<\/code> literals can be used:<\/p>\n<pre><code class=\"language-fsharp\">Tensor.Create([100; 10; 10])<\/code><\/pre>\n<p>Despite this change, F# still continues to use explicit widening of numeric types in most cases. For example, implicit widening does not apply to other numeric types such as <code>int8<\/code> or <code>int16<\/code>, nor from <code>float32<\/code> to <code>float64<\/code>, nor when either source or destination type is unknown. You may also optionally enable the warning <code>\/warnon:3389<\/code>to show a warning at every point op_Implicit is used for method arguments.<\/p>\n<blockquote><p>NOTE: High-performance modern tensor implementations are available through <a href=\"https:\/\/github.com\/dotnet\/TorchSharp\/\">TorchSharp<\/a> and <a href=\"https:\/\/github.com\/SciSharp\/TensorFlow.NET\">TensorFlow.NET<\/a>.<\/p><\/blockquote>\n<h3>First-class support for .NET-style implicit conversions<\/h3>\n<p>The addition of type-directed conversions allows .NET \u201cop_Implicit\u201d conversions to be applied automatically in F# code when calling methods. For example, in F# 5.0 it was necessary to use <code>XName.op_Implicit<\/code> when working with .NET APIs for XML:<\/p>\n<pre><code class=\"language-fsharp\">open System.Xml.Linq\r\n\r\nlet purchaseOrder = XElement.Load(\"PurchaseOrder.xml\")\r\n\r\nlet partNos = purchaseOrder.Descendants(XName.op_Implicit \"Item\")<\/code><\/pre>\n<p>In F# 6, <code>op_Implicit<\/code> conversions are applied automatically for argument expressions when they are available and the types are known for the source expression and target type:<\/p>\n<pre><code class=\"language-fsharp\">open System.Xml.Linq\r\n\r\nlet purchaseOrder = XElement.Load(\"PurchaseOrder.xml\")\r\n\r\nlet partNos = purchaseOrder.Descendants(\"Item\")<\/code><\/pre>\n<p>You may optionally enable the warning <code>\/warnon:3390<\/code> to show a warning at every point op_implicit numeric widening is used, as described below.<\/p>\n<h4>Optional warnings for implicit conversions<\/h4>\n<p>When used widely, or inappropriately, type-directed and implicit conversions can interact poorly with type inference and lead to code that is harder to understand. For this reason, some mitigations are in-place to help ensure this feature is not widely abused in F# code. First, both source and destination type must be strongly known, with no ambiguity or additional type inference arising. Secondly, opt-in warnings can be activated to report any use of implicit conversions, with one warning on by default:<\/p>\n<ul>\n<li><code>\/warnon:3388<\/code> (additional implicit upcast)<\/li>\n<li><code>\/warnon:3389<\/code> (implicit numeric widening)<\/li>\n<li><code>\/warnon:3390<\/code> (op_Implicit at method arguments)<\/li>\n<li><code>\/warnon:3391<\/code> (op_Implicit at non-method arguments, on by default)<\/li>\n<\/ul>\n<p>If your team wants to ban all uses of implicit conversions you can also use <code>\/warnaserror:3388<\/code>, <code>\/warnaserror:3389<\/code>, <code>\/warnaserror:3390<\/code>, <code>\/warnaserror:3391<\/code>.<\/p>\n<h2>Making F# simpler: Updating immutable collections<\/h2>\n<p>This release sees the addition of five new operations to the core collection functions in FSharp.Core. These are:<\/p>\n<ul>\n<li>List\/Array\/Seq.insertAt<\/li>\n<li>List\/Array\/Seq.removeAt<\/li>\n<li>List\/Array\/Seq.updateAt<\/li>\n<li>List\/Array\/Seq.insertManyAt<\/li>\n<li>List\/Array\/Seq.removeManyAt<\/li>\n<\/ul>\n<p>These all perform copy-and-update operations on the corresponding collection type or sequence. Examples of using these functions can be seen in the documentation, e.g. for <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-listmodule.html#insertAt\">List.insertAt<\/a>.<\/p>\n<p>As an example, consider the model, message and update logic for a simple \u201cTodo List\u201d application written in the Elmish style. Here the user interacts with the application, generating messages, and the <code>update<\/code> function processes these messages, producing a new model:<\/p>\n<pre><code class=\"language-fsharp\">type Model =\r\n    { ToDo: string list }\r\n\r\ntype Message =\r\n    | InsertToDo of index: int * what: string\r\n    | RemoveToDo of index: int\r\n    | LoadedToDos of index: int * what: string list\r\n\r\nlet update (model: Model) (message: Message) =\r\n    match message with\r\n    | InsertToDo (index, what) -&gt; \r\n        { model with ToDo = model.ToDo |&gt; List.insertAt index what }\r\n    | RemoveToDo index -&gt; \r\n        { model with ToDo = model.ToDo |&gt; List.removeAt index }\r\n    | LoadedToDos (index, what) -&gt; \r\n        { model with ToDo = model.ToDo |&gt; List.insertManyAt index what }<\/code><\/pre>\n<p>With these new functions, the logic is clear and simple and relies only on immutable data.<\/p>\n<h2>Making F# simpler: Map has Keys and Values<\/h2>\n<p>In FSharp.Core 6.0.0.0 the <code>Map<\/code> type new supports <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-fsharpmap-2.html#Keys\">Keys<\/a> and <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-fsharpmap-2.html#Values\">Values<\/a> properties. These do not copy the underlying collection.<\/p>\n<h2>Making F# simpler: Additional intrinsics for NativePtr<\/h2>\n<p>In FSharp.Core 6.0.0.0 we add new intrinsics to the <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-nativeinterop-nativeptrmodule.html\">NativePtr<\/a> module:<\/p>\n<ul>\n<li><code>NativePtr.nullPtr<\/code><\/li>\n<li><code>NativePtr.isNullPtr<\/code><\/li>\n<li><code>NativePtr.initBlock<\/code><\/li>\n<li><code>NativePtr.clear<\/code><\/li>\n<li><code>NativePtr.copy<\/code><\/li>\n<li><code>NativePtr.copyBlock<\/code><\/li>\n<li><code>NativePtr.ofILSigPtr<\/code><\/li>\n<li><code>NativePtr.toILSigPtr<\/code><\/li>\n<\/ul>\n<p>As with other functions in <code>NativePtr<\/code> these functions are inlined and their use emits warnings unless <code>\/nowarn:9<\/code> is used. The use of these functions is restricted to unmanaged types.<\/p>\n<h2>Making F# more uniform: Additional numeric types with unit annotations<\/h2>\n<p>F# supports <a href=\"https:\/\/docs.microsoft.com\/dotnet\/fsharp\/language-reference\/units-of-measure\">Units of Measure<\/a>, allowing annotation tags to be added to numeric types. However, in previous versions not all numeric types supported these annotations. In F# 6, the following types or type abbreviation aliases now support unit-of-measure annotations, the new additions are shown with a +:<\/p>\n<table>\n<thead>\n<tr>\n<th>F# alias<\/th>\n<th>CLR Type<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>float32<\/code>\/<strong><code>single+<\/code><\/strong>+<\/td>\n<td><code>System.Single<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>float<\/code>\/<strong><code>double<\/code><\/strong>+<\/td>\n<td><code>System.Double<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>decimal<\/code><\/td>\n<td><code>System.Decimal<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>sbyte<\/code>\/<strong><code>int8<\/code><\/strong>+<\/td>\n<td><code>System.SByte<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>int16<\/code><\/td>\n<td><code>System.Int16<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>int<\/code>\/<strong><code>int32<\/code><\/strong>+<\/td>\n<td><code>System.Int32<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>int64<\/code><\/td>\n<td><code>System.Int64<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong><code>byte<\/code><\/strong>+\/<strong><code>uint8<\/code><\/strong>+<\/td>\n<td><code>System.Byte<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong><code>uint16<\/code><\/strong>+<\/td>\n<td><code>System.UInt16<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong><code>uint<\/code><\/strong>+\/<strong><code>uint32<\/code><\/strong>+<\/td>\n<td><code>System.UInt32<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong><code>uint64<\/code><\/strong>+<\/td>\n<td><code>System.UIn64<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong><code>nativeint<\/code><\/strong>+<\/td>\n<td><code>System.IntPtr<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong><code>unativeint<\/code><\/strong>+<\/td>\n<td><code>System.UIntPtr<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For example, you can annotate an unsigned integer as follows:<\/p>\n<pre><code class=\"language-fsharp\">[&lt;Measure&gt;] \r\ntype days\r\n\r\nlet better_age = 3u&lt;days&gt;<\/code><\/pre>\n<p>This design revision was championed, designed and implemented by community member <a href=\"https:\/\/github.com\/pblasucci\">Paulmichael Blasucci<\/a>.<\/p>\n<h2>Bringing F# forward: Reducing use of rarely used symbolic operators<\/h2>\n<p>In F# programming, \u201cref cells\u201d can be used for heap-allocated mutable registers. While they are occasionally useful, in modern F# coding these are rarely needed as <code>let mutable<\/code> can normally be used instead. The F# core library includes two operators <code>:=<\/code> and <code>!<\/code> and two functions <code>incr<\/code> and <code>decr<\/code> specifically related to reference calls. The presence of these operators makes reference cells more central to F# programming than they need to be, requiring all F# programmers to know these operators. Further, the <code>!<\/code> operator can be easily confused with the <code>not<\/code> operation in C# and other languages, a potentially subtle source of bugs when translating code.<\/p>\n<p>As a result, in F# 6 we\u2019ve made a decision to give soft guidance that de-normalizes the use of <code>:=<\/code>, <code>!<\/code>, <code>incr<\/code> and <code>decr<\/code> in F# 6 and beyond. Using these operators and functions will now given informational messages asking you to replace your code with explicit use of the <code>Value<\/code> property.<\/p>\n<p>The rationale for this change is to reduce the number of operators the F# programmer needs to know.<\/p>\n<p>For example, consider the following F# 5.0 code:<\/p>\n<pre><code class=\"language-fsharp\">let r = ref 0\r\n\r\nlet doSomething() =\r\n    printfn \"doing something\"\r\n    r := !r + 1<\/code><\/pre>\n<p>First, in modern F# coding reference cells are rarely needed, as <code>let mutable<\/code> can normally be used instead:<\/p>\n<pre><code class=\"language-fsharp\">let mutable r = 0\r\n\r\nlet doSomething() =\r\n    printfn \"doing something\"\r\n    r &lt;- r + 1<\/code><\/pre>\n<p>If reference cells are used, then the in F# 6 an informational warning is emitted asking you to change the last line to <code>r.Value &lt;- r.Value + 1<\/code>, and linking you to further guidance on the appropriate use of reference cells.<\/p>\n<pre><code class=\"language-fsharp\">let r = ref 0\r\n\r\nlet doSomething() =\r\n    printfn \"doing something\u201d\"\r\n    r.Value &lt;- r.Value + 1<\/code><\/pre>\n<p>These messages are not warnings &#8211; they are &#8220;informational messages&#8221; shown in the IDE. This remains backwards-compatible, and is described in <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1111-refcell-op-information-messages.md\">RFC FS-1111<\/a>.<\/p>\n<h2>Bringing F# forward: Removing long-deprecated legacy features<\/h2>\n<p>F# 2.0 deprecated several F# features, giving warnings if they were used. These features been removed in F# 6.0 and will give errors, unless you explicitly use <code>\/langversion:5.0<\/code> or before. The features that now give errors are:<\/p>\n<ul>\n<li>Multiple generic parameters using a postfix type name, for example <code>(int, int) Dictionary<\/code>. This becomes an error in F# 6 and the standard <code>Dictionary&lt;int,int&gt;<\/code> should be used instead.<\/li>\n<li><code>#indent \"off\"<\/code>. This becomes an error in F# 6<\/li>\n<li><code>x.(expr)<\/code>. This becomes an error in F# 6<\/li>\n<li><code>module M = struct \u2026 end<\/code> . This becomes an error in F# 6<\/li>\n<li>Use of inputs <code>*.ml<\/code> and <code>*.mli<\/code>. This becomes an error in F# 6<\/li>\n<li>Use of <code>(*IF-CAML*)<\/code> or <code>(*IF-OCAML*)<\/code>. This becomes an error in F# 6<\/li>\n<li>Use of <code>land<\/code>, <code>lor<\/code>, <code>lxor<\/code>, <code>lsl<\/code>, <code>lsr<\/code> or <code>asr<\/code> as infix operators. These are infix keywords in F# because they were infix keywords in OCaml and are not defined in FSharp.Core. Using these keywords will now emit a warning (not error)<\/li>\n<\/ul>\n<p>These are described in <a href=\"https:\/\/github.com\/fsharp\/fslang-design\/blob\/main\/FSharp-6.0\/FS-1114-ml-compat-revisions.md\">RFC FS-1114<\/a><\/p>\n<h2>F# tooling: Pipeline debugging!<\/h2>\n<p>One of the most anticipated features in the F# 6 toolchain is the addition of \u201cPipeline debugging\u201d. Now, the F# compiler emits debug stepping points for each position in an F# pipeline involving |&gt;, ||&gt; and |||&gt; operators. At each step, the input or intermediate stage of the pipeline can be inspected in a typical debugger.<\/p>\n<p>For example:<\/p>\n<p><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/pipeline-debugging-step.png\" alt=\"Stepping in pipeline debugging, What\u2019s new in F# 6\" width=\"624\" height=\"151\" \/><\/p>\n<p>Breakpoints can also be set at each point in the pipeline, for example:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/breakpoints-pipeline-debugging.png\" alt=\"Breakpoints in pipeline debugging\" \/><\/p>\n<p>Pipeline debugging activates by default when you re-compile your code with the F# 6 compiler, regardless of the language version or IDE you are using. Play with stepping and breakpoints and let us know what you think!<\/p>\n<h2>F# tooling: Value shadowing shown in debugger<\/h2>\n<p>The updated F# 6 toolchain makes another important improvement to debugging. For example, consider the code<\/p>\n<pre><code class=\"language-fsharp\">let someFunctionUsingShadowing x =\r\n    let yyy = \"aa\"\r\n    let yyy = \"aa\".Length - 1\r\n    yyy + 3 <\/code><\/pre>\n<p>Here the second <code>yyy<\/code> \u201cshadows\u201d the first. This is allowed in F# and the technique is a common one because F# defaults to immutable bindings, hence new versions of bindings often replace previous ones.<\/p>\n<p>When using an F# 6 toolchain, the names associated with locals are adjusted for those portions of scopes where shadowing occurs. For example, when a breakpoint is placed on the expression <code>yyy + 3<\/code> of the above function, the locals are displayed as follows:<\/p>\n<p><img decoding=\"async\" class=\"alignnone\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/value-shadowing.png\" alt=\"Value shadowing in debugger, What\u2019s new in F# 6\" width=\"624\" height=\"138\" \/><\/p>\n<h2>F# tooling: Performance and Scalability<\/h2>\n<p>In F# 6, we have made dramatic improvements to Compiler\/IDE-tooling perf\/scalability improvements in both the core implementation of the language and the Visual Studio components.<\/p>\n<ul>\n<li>The F# compiler now performs the parsing stage in parallel, resulting in approximately 5% performance improvement for large projects.<\/li>\n<li>Analysis results are now performed concurrently. When working in the IDE, analysis requests are no longer serialized through a single \u201creactor\u201d compilation thread. Instead, the F# Compiler Service is now concurrent. This greatly improves performance in many situations.<\/li>\n<li>Improved performance of analysis in F# projects that contain signature files. If you are using signature files in your project you will see diagnostics and other analysis results much more quickly when a change is made to an implementation file without change to the signature file. This change was also included in the final releases of Visual Studio 2019.<\/li>\n<li>Find-all references is now performed concurrently, in parallel across multiple projects.<\/li>\n<li>Major performance improvements to \u201cClose solution\u201d and \u201cSwitch configuration\u201d. For example, some simple use cases have reduced \u201cClose solution\u201d from 16 seconds to 1 second. For a demonstration of this see <a href=\"https:\/\/twitter.com\/TIHan\/status\/1436044454381514752\">this tweet by contributor Will Smith<\/a>.<\/li>\n<\/ul>\n<h2>F# tooling: In-memory cross-project referencing!<\/h2>\n<p>In F# 6, we made working between F# and C# projects simpler and more reliable through \u201cIn-memory cross-project referencing\u201d from F# to C#.<\/p>\n<p>This means in C# projects are now reflected immediately in a F# project without having to compile the C# project on-disk. It also means analysis results are available in uncompiled solutions.<\/p>\n<h2>F# tooling: .NET Core the default for scripting<\/h2>\n<p>If you open or execute an F# Script (<code>.fsx<\/code>) in Visual Studio, by default the script will be analysed and executed using .NET Core with 64-bit execution. This functionality was in preview in Visual Studio 2019 and is now enabled by default.<\/p>\n<p>To enable .NET Framework scripting, use <code>Tools -&gt; Options -&gt; F# Tools -&gt; F# Interactive<\/code> and set <code>Use .NET Core Scripting<\/code> to <code>false<\/code> and restart the F# Interactive window. This setting affects both script editing and script execution.<\/p>\n<p>64-bit scripting is now also the default. To enable 32-bit execution for .NET Framework scripting, also set <code>64-bit F# Interactive<\/code> to <code>false<\/code>. There is no 32-bit option for .NET Core scripting.<\/p>\n<h2>F# tooling: F# scripts now respect global.json<\/h2>\n<p>If you execute a script using <code>dotnet fsi<\/code> in a directory containing a <code>global.json<\/code> with a .NET SDK setting, then the listed version of the .NET SDK will be used to execute and for editing the the script. This feature has been in preview in the later versions of .NET 5.<\/p>\n<p>For example, assume is a script is in a directory with the following <code>global.json<\/code> specifying a .NET SDK version policy:<\/p>\n<pre><code class=\"language-json\">{\r\n  \"sdk\": {\r\n    \"version\": \"5.0.200\",\r\n    \"rollForward\": \"minor\"\r\n  }\r\n}<\/code><\/pre>\n<p>This is a powerful feature that lets you &#8220;lock down&#8221; the SDK used to compile, analyse and execute your scripts.<\/p>\n<ul>\n<li>If you now execute the script using <code>dotnet fsi<\/code>, from this directory, the SDK version will be respected. If the SDK is not found, you may need to install it on your development machine.<\/li>\n<li>Visual Studio and other IDEs will respect this setting when you are editing script.<\/li>\n<li>When you start or reset the F# Interactive evaluation window in Visual Studio, the SDK choice is delayed until you first use &#8220;Send to Interactive&#8221; (Alt-Enter) from the script. At this point, the SDK chosen will the one used for editing and executing the script.<\/li>\n<\/ul>\n<p>On Linux and other UNIX systems you can combine a <code>global.json<\/code> with a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Shebang_(Unix)\">shebang<\/a> with a language version for direct execution of the script. A simple shebang for <code>script.fsx<\/code> is:<\/p>\n<pre><code class=\"language-fsharp\">#!\/usr\/bin\/env -S dotnet fsi\r\n\r\nprintfn \"Hello, world\"<\/code><\/pre>\n<p>The script can be executed directly with <code>script.fsx<\/code>. You can combine this with a specific, non-default language version like this:<\/p>\n<pre><code class=\"language-fsharp\">#!\/usr\/bin\/env -S dotnet fsi --langversion:5.0<\/code><\/pre>\n<p>Note that this setting will be ignored by editing tools, which will analyse the script assuming latest language version.<\/p>\n<h2>F# tooling: .NET Interactive in Visual Studio Code and Visual Studio!<\/h2>\n<p><a href=\"https:\/\/github.com\/dotnet\/interactive#notebooks-with-net\">.NET Interactive Notebooks<\/a> allow you to use notebook-style programming with F# and C#. Many improvements have been made in recent releases including excellent support in Visual Studio Code.<\/p>\n<p>Also <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/ml-net-and-model-builder-october-updates\/\">just announced<\/a> is a <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=MLNET.notebook\">Notebook Editor extension for Visual Studio 2022<\/a>.<\/p>\n<h2>Making F# simpler to learn: Code Examples!<\/h2>\n<p>In October, the F# community has worked on an initiative to add code examples for all public entry points to the F# Core Library. 800 code examples have now been contributed! For example:<\/p>\n<ul>\n<li>All functions in the <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-listmodule.html\">List<\/a>, <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-arraymodule.html\">Array<\/a>, <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-seqmodule.html\">Seq<\/a> and <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-collections-mapmodule.html\">Map<\/a> modules now have code examples.<\/li>\n<li>Functions and methods in advanced modules such as <a href=\"https:\/\/fsharp.github.io\/fsharp-core-docs\/reference\/fsharp-quotations-fsharpexpr.html\">Quotations<\/a> now have examples.<\/li>\n<\/ul>\n<p>You can contribute to this initiative via <a href=\"https:\/\/github.com\/dotnet\/fsharp\/issues\/12124\">this GitHub issue<\/a>.<\/p>\n<h2>System.Text.Json support for common F# types<\/h2>\n<p>Starting with .NET 6 System.Text.Json will have built-in support for common F# types. An example is shown below.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/json.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-36482\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/json.jpg\" alt=\"Image json from f#\" width=\"680\" height=\"340\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/json.jpg 680w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/json-300x150.jpg 300w\" sizes=\"(max-width: 680px) 100vw, 680px\" \/><\/a><\/p>\n<p>User-defined discriminated unions are not yet supported in this way. Thank you to <a href=\"https:\/\/github.com\/eiriktsarpalis\">Eirik Tsarpalis<\/a> for contributing this to .NET.<\/p>\n<h2>General Improvements in .NET 6<\/h2>\n<p>F# 6 is built on .NET 6, and F# programmers benefit both directly and indirectly from a host of new features and improvements in the runtime. Some of these are listed below, summarized from the announcements for <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-release-candidate-1\/\">.NET 6 Release Candidate 1<\/a> and previous release announcements.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/source-build\">Source build<\/a>, a scenario and infrastructure being developed with Red Hat that is intended to satisfy packaging rules of commonly used Linux distributions, such as Debian and Fedora. Also, source build is intended to enable .NET Core contributors to build a .NET Core SDK with coordinated changes in multiple repositories. The technology is intended to solve common challenges that developers encounter when trying to build the whole .NET Core SDK from source.<\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/conversation-about-pgo\/\">Profile-guided optimization<\/a>, which is based on the assumption that code executed as part of a startup often is uniform and that higher level performance can be delivered by leveraging it. PGO can compile startup code at higher quality, reduce binary size, and rearrange application binaries so code used at startup is co-located near the start of the file.<\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/43618\">Dynamic PGO<\/a>, a mirror image of PGO, integrated with the RyuJIT .NET just-in-time compiler. Performance is improved.<\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-release-candidate-1\/#crossgen2\">Crossgen2<\/a>, to generate and optimize code via ahead-of-time compilation, is now enabled by default when publishing ReadyToRun images.<\/li>\n<li><a href=\"https:\/\/newsroom.intel.com\/editorials\/intel-cet-answers-call-protect-common-malware-threats\/\">Intel Control Enforcement Technology (CET)<\/a>, available in some new Intel and AMD processors to protect against common types of attacks involving control-flow hijacking.<\/li>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/HTTP\/3\">HTTP\/3<\/a>, previewed in .NET 6, solves functional and performance challenges with previous versions of HTTP.<\/li>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/W%5EX\">W^X<\/a>, a security mitigation to block attack paths by disallowing memory pages to be writable and executable at the same time.<\/li>\n<\/ul>\n<p>Other improvements in .NET 6 include:<\/p>\n<ul>\n<li>Interface casting performance has been improved by 16 percent to 38 percent.<\/li>\n<li>Code generation has been improved in RyuJIT via multiple changes, to make the process more efficient or resulting code run faster.<\/li>\n<li>Single-file bundles now support compression.<\/li>\n<li>Single-file application publishing improvements including improved analysis to allow for custom warnings.<\/li>\n<li>Enhanced date, time, and time zone support.<\/li>\n<li>Significantly improved FileStream performance on Windows.<\/li>\n<li>OpenSSL 3 support has been added for cryptography on Linux.<\/li>\n<li>OpenTelemetry Metrics API support has been added. OpenTelemetry, which has been supported in recent .NET versions, promotes observability.<\/li>\n<li>WebSocket compression for libraries reduces the amount of data transmitted over a network.<\/li>\n<li>Package validation tools enable NuGet library developers to validate that packages are consistent and well-formed.<\/li>\n<li>TLS support for DirectoryServices.Protocols.<\/li>\n<li>Native memory allocation APIs.<\/li>\n<\/ul>\n<h2>General Improvements in Visual Studio<\/h2>\n<p>The release of F# 6 coincides with the release of Visual Studio 2022 on Windows. F# programmers using this IDE experience will benefit from many improvements in this release:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/visualstudio\/ide\/whats-new-visual-studio-2022?view=vs-2019#visual-studio-2022-is-64-bit\">Visual Studio 2022 on Windows is now a 64-bit application<\/a>. This means you can open, edit, run, and debug even the biggest and most complex solutions without running out of memory.<\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/visualstudio\/ide\/whats-new-visual-studio-2022?view=vs-2019#find-in-files-is-faster\">Find in Files is faster<\/a>. Find in Files is now as much as 3x faster when searching large solutions such as Orchard Core.<\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/visualstudio\/ide\/whats-new-visual-studio-2022?view=vs-2019#multi-repo-support-with-git-in-the-ide\">Multi-repo support with Git in the IDE<\/a>. If you&#8217;ve worked with projects hosted on different Git repositories, you might have used external tools or multiple instances of Visual Studio to connect to them. With Visual Studio 2022, you can work with a single solution that has projects in multiple repositories and contribute to them all from a single instance of Visual Studio.<\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/visualstudio\/ide\/whats-new-visual-studio-2022?view=vs-2019#personalization-improvements\">Personalization improvements<\/a>. For example, Visual Studio 2022 offers you the ability to sync with your Windows theme &#8211; if you&#8217;ve enabled the &#8220;night light&#8221; feature there, Visual Studio uses it, too.<\/li>\n<\/ul>\n<h2>What&#8217;s next<\/h2>\n<p>Now that F# 6 is released, we&#8217;re moving our focus to a few areas:<\/p>\n<ol>\n<li>Simplifying the F# learning experience<\/li>\n<li>Continuing to modernize the F# language service implementation<\/li>\n<li>Planning for the next F# version<\/li>\n<\/ol>\n<p>Cheers, and happy F# coding!<\/p>\n<h2>Thanks and Acknowledgments!<\/h2>\n<p>F# is developed as a collaboration between the .NET Foundation, the F# Software Foundation, their members and other contributors including Microsoft. The F# community is involved at all stages of innovation, design, implementation and delivery and we&#8217;re proud to be a contributing part of this community.<\/p>\n<p>Many people have contributed directly and indirectly to F# 6, including all who have contributed to the F# Language Design Process through <a href=\"https:\/\/github.com\/fsharp\/fslang-suggestions\/\">fsharp\/fslang-suggestions<\/a> and <a href=\"https:\/\/github.com\/fsharp\/fslang-design\">fsharp\/fslang-design<\/a> repositories. <a href=\"https:\/\/github.com\/rspeele\">Robert Peele<\/a> developed <a href=\"https:\/\/github.com\/rspeele\/TaskBuilder.fs\">TaskBuilder.fs<\/a> and <a href=\"https:\/\/github.com\/NinoFloris\">Nino Floris<\/a> developed <a href=\"https:\/\/github.com\/crowded\/ply\">Ply<\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/TIHan\">Will Smith<\/a>, <a href=\"https:\/\/github.com\/KevinRansom\">Kevin Ransom<\/a>, <a href=\"https:\/\/github.com\/vzarytovskii\">Vlad Zarytovskii<\/a>, <a href=\"https:\/\/github.com\/cartermp\">Phillip Carter<\/a>, <a href=\"https:\/\/github.com\/dsyme\">Don Syme<\/a>, <a href=\"https:\/\/github.com\/brettfo\">Brett V. Forsgren<\/a> contributed directly at Microsoft under the guidance of <a href=\"https:\/\/github.com\/jonsequitur\">Jon Sequeira<\/a> and <a href=\"https:\/\/github.com\/timheuer\">Tim Heuer<\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/auduchinok\">Eugene Auduchinok<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=auduchinok&amp;since=2020-09-21&amp;until=2021-10-13\">41 PRs<\/a> to the F# core implementation, including significant improvements to error recovery. <a href=\"https:\/\/github.com\/nojaf\">Florian Verdonck<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=nojaf&amp;since=2020-09-21&amp;until=2021-10-13\">24 PRs<\/a>, including improved source trees for the <a href=\"https:\/\/github.com\/fsprojects\/fantomas#fantomas\">Fantomas<\/a> source code formatter. <a href=\"https:\/\/github.com\/Happypig375\">Hadrian Tang<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=nojaf&amp;since=2020-09-21&amp;until=2021-10-13\">22 PRs<\/a>, including several of the language features and simplifications outlined in this blog post. GitHub user <a href=\"https:\/\/github.com\/kerams\">kerams<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=kerams&amp;since=2020-09-21&amp;until=2021-10-13\">13 pull requests<\/a>, including support for SkipLocalsInit and performance improvements. <a href=\"https:\/\/github.com\/ScottHutchinson\">Scott Hutchinson<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=ScottHutchinson&amp;since=2020-09-21&amp;until=2021-10-13\">9 PRs<\/a>, <a href=\"https:\/\/twitter.com\/GoswinR\">Goswin Rothenthal<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=goswinr&amp;since=2020-09-21&amp;until=2021-10-13\">7 PRs<\/a>, <a href=\"https:\/\/twitter.com\/vagabond_code\">Ryan Coy<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=laenas&amp;since=2020-09-21&amp;until=2021-10-13\">6 PRs<\/a>, <a href=\"https:\/\/github.com\/buybackoff\">Victor Baybekov<\/a> made <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=buybackoff&amp;since=2020-09-21&amp;until=2021-10-13\">5 PRs<\/a>, including performance improvements to Map and Set in FSharp.Core. Some of these improvements were shipped in later versions of FSharp.Core 5.0.x.<\/p>\n<p>Other direct contributors to the <a href=\"https:\/\/github.com\/dotnet\/fsharp\">dotnet\/fsharp<\/a> repository in the F# 6.0 time period include <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=forki&amp;since=2020-09-21&amp;until=2021-10-13\">forki<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=smoothdeveloper&amp;since=2020-09-21&amp;until=2021-10-13\">smoothdeveloper<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=gsomix&amp;since=2020-09-21&amp;until=2021-10-13\">gsomix<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=cristianosuzuki77&amp;since=2020-09-21&amp;until=2021-10-13\">cristianosuzuki77<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=ErikSchierboom&amp;since=2020-09-21&amp;until=2021-10-13\">ErikSchierboom<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=jonfortescue&amp;since=2020-09-21&amp;until=2021-10-13\">jonfortescue<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=teo-tsirpanis&amp;since=2020-09-21&amp;until=2021-10-13\">teo-tsirpanis<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=MaxWilson&amp;since=2020-09-21&amp;until=2021-10-13\">MaxWilson<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=mmitche&amp;since=2020-09-21&amp;until=2021-10-13\">mmitche<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=DedSec256&amp;since=2020-09-21&amp;until=2021-10-13\">DedSec256<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=uxsoft&amp;since=2020-09-21&amp;until=2021-10-13\">uxsoft<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=Swoorup&amp;since=2020-09-21&amp;until=2021-10-13\">Swoorup<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=En3Tho&amp;since=2020-09-21&amp;until=2021-10-13\">En3Tho<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=0x6a62&amp;since=2020-09-21&amp;until=2021-10-13\">0x6a62<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=uweigand&amp;since=2020-09-21&amp;until=2021-10-13\">uweigand<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=MecuStefan&amp;since=2020-09-21&amp;until=2021-10-13\">MecuStefan<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=JYCabello&amp;since=2020-09-21&amp;until=2021-10-13\">JYCabello<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=yatli&amp;since=2020-09-21&amp;until=2021-10-13\">Yatao Li<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=amieres&amp;since=2020-09-21&amp;until=2021-10-13\">amieres<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=chillitom&amp;since=2020-09-21&amp;until=2021-10-13\">chillitom<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=Daniel-Svensson&amp;since=2020-09-21&amp;until=2021-10-13\">Daniel-Svensson<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=Krzysztof-Cieslak&amp;since=2020-09-21&amp;until=2021-10-13\">Krzysztof-Cieslak<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=thinkbeforecoding&amp;since=2020-09-21&amp;until=2021-10-13\">thinkbeforecoding<\/a>, <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=abelbraaksma&amp;since=2020-09-21&amp;until=2021-10-13\">abelbraaksma<\/a> and <a href=\"https:\/\/github.com\/dotnet\/fsharp\/commits?author=ShalokShalom&amp;since=2020-09-21&amp;until=2021-10-13\">ShalokShalom<\/a>.<\/p>\n<p>Many other people are contributing to the rollout of F# 6 and .NET 6 in <a href=\"https:\/\/fable.io\/\">Fable<\/a>, <a href=\"https:\/\/ionide.io\/\">Ionide<\/a>, <a href=\"https:\/\/fsbolero.io\/\">Bolero<\/a>, <a href=\"https:\/\/fsprojects.github.io\/FSharp.Data\/\">FSharp.Data<\/a>, <a href=\"https:\/\/github.com\/giraffe-fsharp\/Giraffe#giraffe\">Giraffe<\/a>, <a href=\"https:\/\/github.com\/SaturnFramework\/Saturn\">Saturn<\/a>, <a href=\"https:\/\/safe-stack.github.io\/\">SAFE Stack<\/a>, <a href=\"https:\/\/websharper.com\/\">WebSharper<\/a>, <a href=\"https:\/\/fscheck.github.io\/FsCheck\/\">FsCheck<\/a>, <a href=\"https:\/\/diffsharp.github.io\/\">DiffSharp<\/a>, <a href=\"https:\/\/github.com\/fsprojects\/fantomas#fantomas\">Fantomas<\/a> and other community-delivered technologies.<\/p>\n<h2>Contributor Showcase<\/h2>\n<p>In this and future announcements we will highlight some of the individuals who contribute to F#. This text is written in the contributors\u2019 own words:<\/p>\n<blockquote><p>I&#8217;m Nino Floris, co-founder of Crowded and contributor to Npgsql and other projects. At Crowded we endeavor to create a friendly community platform, written in F# with a focus on fast apis and principled flexibility. I am interested in statically typed programming languages that bring adaptable, performant, and usable programming experiences to more places. Small open source communities with big impact hold a special place in my heart \u2013 when I&#8217;m not busy with work you may see me contributing to Npgsql, (web) frameworks, or sharing my enthusiasm for programming by helping people in the community.<\/p><\/blockquote>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/nino-floris.jpg\" alt=\"Contributor photo\" \/><\/p>\n<blockquote><p>I&#8217;m Hadrian Tang, a 19-year-old student at Hong Kong University of Science and Technology studying Information Systems for the second year. I started programming in 2014 by picking up a book on VB.NET at the school library. I moved to C#, then started looking into F# after reading <a href=\"https:\/\/github.com\/verybadcat\/CSharpMath\/issues\/4\">a comment by Charles Roddie<\/a> in 2018. I was reluctant to adopt F#, but the simple syntax and interoperability ultimately won me over. However, like every language, F# has much to improve, which is why I&#8217;m the author of 17% of currently open issues at the F# suggestions repo. Last summer, I took a shot at some of the easy features that ultimately made it to F# 6. I use F# for mobile development using and for my next project plan to use Fable and web interfaces to improve interoperability with JavaScript&#8217;s huge array of libraries, teaming up with [WhiteBlackGoose] (https:\/\/github.com\/WhiteBlackGoose).<\/p>\n<p>Much thanks to Don Syme for creating such an amazing language with simple syntax and great interoperability, and to the <a href=\"https:\/\/discord.gg\/R6n7c54\">F# Discord<\/a> for a great place to help each other: I could get help from the community with any problems that I faced. Moreover, GitHub and .NET also give a great foundation for all F# work. I love how F# is agile: starting PRs to implement unapproved features can lead to approval. I look forward to the future of F#, especially with the theme of making F# simple! And much thanks to the F# community as a whole for libraries, tooling and support!<\/p><\/blockquote>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/10\/hadrian-tang.jpeg\" alt=\"Hadrian Tang photo\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>F# 6 is now a release candidate. Checkout all of the new features available in this release.<\/p>\n","protected":false},"author":1097,"featured_media":36113,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,636],"tags":[73,7260],"class_list":["post-36112","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-fsharp","tag-f","tag-f-6"],"acf":[],"blog_post_summary":"<p>F# 6 is now a release candidate. Checkout all of the new features available in this release.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/36112","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\/1097"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=36112"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/36112\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/36113"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=36112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=36112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=36112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}