https://devblogs.microsoft.com/dotnet/whats-new-in-fsharp-6/ Skip to main content [RE1Mu3b] Microsoft .NET Blog .NET Blog .NET Blog * Home * DevBlogs * Developer + Visual Studio + Visual Studio Code + Visual Studio for Mac + DevOps + Developer support + CSE Developer + Engineering@Microsoft + Azure SDK + IoT + Command Line + Perf and Diagnostics + Dr. International + Notification Hubs + Math in Office * Technology + DirectX + PIX + SurfaceDuo + Startups + Sustainable Engineering + Windows AI Platform * Languages + C++ + Java + Java Blog in Chinese + JavaScript + PowerShell Community + PowerShell Team + Python + Q# + TypeScript + Visual Basic + Visual C# + Visual F# * .NET + .NET + .NET MAUI + Blazor + ASP.NET + NuGet + Xamarin * Platform Development + #ifdef Windows + Apps for Windows + Azure Depth Platform + Azure Government + Bing Dev Center + Microsoft Edge Dev + Microsoft Azure + Microsoft 365 Developer + Old New Thing + Windows MIDI and Music dev + Windows Search Platform * Data Development + Azure Cosmos DB + Azure Data Studio + Azure SQL + OData + Revolutions R + SQL Server Data Tools * More [ ] Search Search Cancel .NET Conf 2021 .NET Conf is coming! November 9th through the 11th is a free, three-day, virtual developer event that celebrates the major releases of the .NET development platform. Save the Date! Close What's new in F# 6 [png] Kathleen October 19th, 2021 We're excited to announce the availability F# 6, shipping with .NET 6 RC2 and Visual Studio 2022 RC2. It'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: * Install the latest .NET 6 SDK RC2 preview * Install Visual Studio 2022 RC2 preview * Use .NET Interactive Notebooks in Jupyter or VS Code 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. To learn more about F#, see The .NET Conf Focus Day on F# including the F# Bonanza, Guido van Rossum Learns F# and Starting Your F# Journey. Making F# faster and more interopable with task {...} One of the most requested features for F# - and the most significant technical feature in this release - 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 async {...} to create a task and then invoking it with Async.AwaitTask. With F# 6 you can now use task {...} directly to create the task and await it. For example, consider the following F# code to create a .NET-compatible task: let readFilesTask (path1, path2) = async { let! bytes1 = File.ReadAllBytesAsync(path1) |> Async.AwaitTask let! bytes2 = File.ReadAllBytesAsync(path2) |> Async.AwaitTask return Array.append bytes1 bytes2 } |> Async.StartAsTask This code can now become: let readFilesTask (path1, path2) = task { let! bytes1 = File.ReadAllBytesAsync(path1) let! bytes2 = File.ReadAllBytesAsync(path2) return Array.append bytes1 bytes2 } The built-in support for task {...} is available ubiquitously in F# code - no namespaces need to be opened. 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. Using task {...} is very similar to async {...}, and both are supported. Using task {...} has several advantages over async {...}: * The performance of task {...} is much better. * Debugging stepping and stack traces for task {...} is better. * Interoperating with .NET packages expecting or producing tasks is easier. If you're familiar with async {...}, there are some differences to be aware of: * task {...} immediately executes the task to the first asynchronous yield. * task {...} does not implicitly propagate a cancellation token. * task {...} does not perform implicit cancellation checks. * task {...} does not support asynchronous tailcalls. This means using return! .. recursively may result in stack overflows if there are no intervening asynchronous yields. In general, you should consider using task {...} over async {...} in new code if interoperating with .NET libraries that uses tasks. Review code before switching to task {...} to ensure you are not relying on the above characteristics of async {...}. The task {...} support of F# 6 is built on a foundation called "resumable code" RFC FS-1087. Resumable code is a core technical feature which can be used to build many kinds of high-performance asynchronous and yielding state machines. In the coming months we will be working with the F# community to utilise this feature to make available two key optional packages: 1. A fast re-implementation of F# async {...} using resumable code. 2. A fast re-implementation of asynchronous sequences asyncSeq {...} using resumable code. Initially these will be delivered via community packages such as FSharp.Control.AsyncSeq. In future versions they may be integrated into FSharp.Core. Making F# simpler to learn: indexing with expr[idx] In F# 6, we begin allowing the syntax expr[idx] for indexing syntax. Up to and including F# 5.0, F# has used expr.[idx] as indexing syntax. This syntax was based on a similar notation used in OCaml for string indexed lookup. Allowing the use of expr[idx] 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. This is not a breaking change - by default no warnings are emitted on the use of expr.[idx]. 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 (/warnon:3566) can be activated to start reporting uses of the expr.[idx] notation. See Indexer Notation for details. In new code, we recommend the systematic use of expr[idx] as the indexing syntax. Making F# faster: Struct representations for partial active patterns F# includes the active patterns feature that allows users to extend pattern matching in intuitive and powerful ways. In F# 6 we've augmented that feature with optional [Struct representations for active patterns] (https://github.com/fsharp/fslang-design/blob/main/ FSharp-6.0/FS-1039-struct-representation-for-active-patterns.md). This allows you to use an attribute to constrain a partial active pattern to return a value option: [] let (|Int|_|) str = match System.Int32.TryParse(str) with | true, int -> ValueSome(int) | _ -> ValueNone The use of the attribute is required. At usage sites, code doesn't change. The net result is that allocations are reduced. Making F# more uniform: overloaded custom operations in computation expressions F# 6 activates the feature "overloaded custom operations in computation expressions" which has been in preview since F# 5.0. This allows for simpler DSLs in F# including for validation and web programming. The feature was previously described in the announcement for F# 5.0 preview and implements F# RFC 1056. Making F# more uniform: "as" patterns In F# 6, the right hand side of an "as" 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 type Pair = Pair of int * int let analyzeObject (input: obj) = match input with | :? (int * int) as (x, y) -> printfn $"A tuple: {x}, {y}" | :? Pair as Pair (x, y) -> printfn $"A DU: {x}, {y}" | _ -> printfn "Nope" let input = box (1, 2) In each pattern case the input object is type-tested. The right-hand-side of the "as" pattern is now allowed to be a further pattern which can itself match the object at the stronger type. Making F# more uniform: Indentation syntax revisions 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#'s use of indentation-aware syntax, see RFC FS-1108. This resolved 10 significant issues highlighted by the F# users since F# 4.0. For example, in F# 5.0 the following was allowed: let c = ( printfn "aaaa" printfn "bbbb" ) However the following was not (producing a warning) let c = [ 1 2 ] In F# 6, both are allowed. This makes F# simpler and easier to learn. The F# community contributor Hadrian Tang has led the way on this including remarkable and highly valuable systematic testing of the feature. Making F# more uniform: Discards on use bindings F# 6 allows _ to be used in a use binding, for example: let doSomething () = use _ = System.IO.File.OpenText("input.txt") printfn "reading the file" This feature implements F# RFC FS-1102. Making F# more uniform: Formatting for binary numbers F# 6 adds the %B pattern to the available format specifiers for binary number formats. Consider the following F# code: printf "%o" 123 printf "%B" 123 This code prints the following output: 173 1111011 This feature implements F# RFC FS-1100. Making F# faster: InlineIfLambda In F# 6, we've added a new declarative feature that allows code to optionally indicate that lambda arguments should be inlined at callsites. For example, consider the following iterate function to traverse an array: let inline iterateTwice ([] action) (array: 'T[]) = for j = 0 to array.Length-1 do action array.[j] for j = 0 to array.Length-1 do action array.[j] If the callsite is let arr = [| 1.. 100 |] let mutable sum = 0 arr |> iterateTwice (fun x -> sum <- sum + x) then after inlining and other optimizations the code becomes: let arr = [| 1.. 100 |] let mutable sum = 0 for j = 0 to array.Length-1 do sum <- array.[i] + x for j = 0 to array.Length-1 do sum <- array.[i] + x Unlike previous versions of F#, this optimization applied regardless of the size of the lambda expression involved. This feature can also be used to implement loop unrolling and similar transformations reliably. An opt-in warning (/warnon:3517, off by default) can be turned on to indicate places in your code where InlineIfLambda 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. Making F# faster: Improved performance and debugging for list and array expressions In F# 6, the compiled form of generative list and array expressions is now up to 4x faster (see the relevant pull request). Generative list and array expressions also have greatly improved debugging. For example: let generateList (i: int) = [ "a" "b" for j in 1 .. 10 do "c" if i % 3 = 0 then "d" "e" ] 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 Making F# simpler and more interoperable: Implicit conversions In F# 6 we have activated support for additional "implicit" and "type-directed" conversions in F#, as described in RFC FS-1093. This change achieves three things. 1. Fewer explicit upcasts are required 2. Fewer explicit integer conversions are required 3. First-class support for .NET-style implicit conversions is added Additional implicit upcast conversions 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): open System open System.IO let findInputSource () : TextReader = if DateTime.Now.DayOfWeek = DayOfWeek.Monday then // On Monday a TextReader Console.In else // On other days a StreamReader File.OpenText("path.txt") :> TextReader 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: let findInputSource () : TextReader = if DateTime.Now.DayOfWeek = DayOfWeek.Monday then // On Monday a TextReader Console.In else // On other days a StreamReader File.OpenText("path.txt") You may optionally enable the warning /warnon:3388 to show a warning at every point an additional implicit upcast is used, as described below. Implicit integer conversions 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: type Tensor(...) = static member Create(sizes: seq) = Tensor(...) In F# 5.0, integer literals for int64 must be used: Tensor.Create([100L; 10L; 10L]) or Tensor.Create([int64 100; int64 10; int64 10]) In F# 6, widening happens automatically for int32 to int64, int32 to nativeint and int32 to double, when both source and destination type are known during type inference, so in cases such as the above int32 literals can be used: Tensor.Create([100; 10; 10]) 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 int8 or int16, nor from float32 to float64, nor when either source or destination type is unknown. You may also optionally enable the warning /warnon:3389to show a warning at every point implicit numeric widening is used, as described below. NOTE: High-performance modern tensor implementations are available through TorchSharp and TensorFlow.NET. First-class support for .NET-style implicit conversions The addition of type-directed conversions allows .NET "op_Implicit" conversions to be applied automatically in F# code when calling methods. For example, in F# 5.0 it was necessary to use XName.op_Implicit when working with .NET APIs for XML: open System.Xml.Linq let purchaseOrder = XElement.Load("PurchaseOrder.xml") let partNos = purchaseOrder.Descendants(XName.op_Implicit "Item") In F# 6, op_Implicit conversions are applied automatically for argument expressions when they are available and the types are known for the source expression and target type: open System.Xml.Linq let purchaseOrder = XElement.Load("PurchaseOrder.xml") let partNos = purchaseOrder.Descendants("Item") You may optionally enable the warning /warnon:3390 to show a warning at every point implicit numeric widening is used, as described below. Optional warnings for implicit conversions 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: * /warnon:3388 (additional implicit upcast) * /warnon:3389 (implicit numeric widening) * /warnon:3390 (op_Implicit at method arguments) * /warnon:3391 (op_Implicit at non-method arguments, on by default) If your team wants to ban all uses of implicit conversions you can also use /warnaserror:3388, /warnaserror:3389, /warnaserror:3390, / warnaserror:3391. Making F# simpler: Updating immutable collections This release sees the addition of five new operations to the core collection functions in FSharp.Core. These are: * List/Array/Seq.insertAt * List/Array/Seq.removeAt * List/Array/Seq.updateAt * List/Array/Seq.insertManyAt * List/Array/Seq.removeManyAt 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 List.insertAt. As an example, consider the model, message and update logic for a simple "Todo List" application written in the Elmish style. Here the user interacts with the application, generating messages, and the update function processes these messages, producing a new model: type Model = { ToDo: string list } type Message = | InsertToDo of index: int * what: string | RemoveToDo of index: int | LoadedToDos of index: int * what: string list let update (model: Model) (message: Message) = match message with | InsertToDo (index, what) -> { model with ToDo = model.ToDo |> List.insertAt index what } | RemoveToDo index -> { model with ToDo = model.ToDo |> List.removeAt index } | LoadedToDos (index, what) -> { model with ToDo = model.ToDo |> List.insertManyAt index what } With these new functions, the logic is clear and simple and relies only on immutable data. Making F# simpler: Map has Keys and Values In FSharp.Core 6.0.0.0 the Map type new supports Keys and Values properties. These do not copy the underlying collection. Making F# simpler: Additional intrinsics for NativePtr In FSharp.Core 6.0.0.0 we add new intrinsics to the NativePtr module: * NativePtr.nullPtr * NativePtr.isNullPtr * NativePtr.initBlock * NativePtr.clear * NativePtr.copy * NativePtr.copyBlock * NativePtr.ofILSigPtr * NativePtr.toILSigPtr As with other functions in NativePtr these functions are inlined and their use emits warnings unless /nowarn:9 is used. The use of these functions is restricted to unmanaged types. Making F# more uniform: Additional numeric types with unit annotations F# supports Units of Measure, 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 in bold: F# alias CLR Type float32/single System.Single float/double System.Double decimal System.Decimal sbyte/int8 System.SByte int16 System.Int16 int/int32 System.Int32 int64 System.Int64 byte/uint8 System.Byte uint16 System.UInt16 uint/uint32 System.UInt32 uint64 System.UIn64 nativeint System.IntPtr unativeint System.UIntPtr For example, you can annotate an unsigned integer as follows: [] type days let better_age = 3u This design revision was championed, designed and implemented by community member Paulmichael Blasucci. Bringing F# forward: Reducing use of rarely used symbolic operators In F# programming, "ref cells" can be used for heap-allocated mutable registers. While they are occasionally useful, in modern F# coding these are rarely needed as let mutable can normally be used instead. The F# core library includes two operators := and ! and two functions incr and decr 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 ! operator can be easily confused with the not operation in C# and other languages, a potentially subtle source of bugs when translating code. As a result, in F# 6 we've made a decision to give soft guidance that de-normalizes the use of :=, !, incr and decr 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 Value property. The rationale for this change is to reduce the number of operators the F# programmer needs to know. For example, consider the following F# 5.0 code: let r = ref 0 let doSomething() = printfn "doing something" r := !r + 1 First, in modern F# coding reference cells are rarely needed, as let mutable can normally be used instead: let mutable r = 0 let doSomething() = printfn "doing something" r <- r + 1 If reference cells are used, then the in F# 6 an informational warning is emitted asking you to change the last line to r.Value <- r.Value + 1, and linking you to further guidance on the appropriate use of reference cells. let r = ref 0 let doSomething() = printfn "doing something" r.Value <- r.Value + 1 These messages are not warnings - they are "informational messages" shown in the IDE. This remains backwards-compatible, and is described in RFC FS-1111. Bringing F# forward: Removing long-deprecated legacy features 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 /langversion:5.0 or before. The features that now give errors are: * Multiple generic parameters using a postfix type name, for example (int, int) Dictionary. This becomes an error in F# 6 and the standard Dictionary should be used instead. * #indent "off". This becomes an error in F# 6 * x.(expr). This becomes an error in F# 6 * module M = struct ... end . This becomes an error in F# 6 * Use of inputs *.ml and *.mli. This becomes an error in F# 6 * Use of (*IF-CAML*) or (*IF-OCAML*). This becomes an error in F# 6 * Use of land, lor, lxor, lsl, lsr or asr 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) These are described in RFC FS-1114 F# tooling: Pipeline debugging! One of the most anticipated features in the F# 6 toolchain is the addition of "Pipeline debugging". Now, the F# compiler emits debug stepping points for each position in an F# pipeline involving |>, ||> and |||> operators. At each step, the input or intermediate stage of the pipeline can be inspected in a typical debugger. For example: Stepping in pipeline debugging, What's new in F# 6 Breakpoints can also be set at each point in the pipeline, for example: Breakpoints in pipeline debugging 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! F# tooling: Value shadowing shown in debugger The updated F# 6 toolchain makes another important improvement to debugging. For example, consider the code let someFunctionUsingShadowing x = let yyy = "aa" let yyy = "aa".Length - 1 yyy + 3 Here the second yyy "shadows" 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. 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 yyy + 3 of the above function, the locals are displayed as follows: Value shadowing in debugger, What's new in F# 6 F# tooling: Performance and Scalability 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. * The F# compiler now performs the parsing stage in parallel, resulting in approximately 5% performance improvement for large projects. * Analysis results are now performed concurrently. When working in the IDE, analysis requests are no longer serialized through a single "reactor" compilation thread. Instead, the F# Compiler Service is now concurrent. This greatly improves performance in many situations. * 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. * Find-all references is now performed concurrently, in parallel across multiple projects. * Major performance improvements to "Close solution" and "Switch configuration". For example, some simple use cases have reduced "Close solution" from 16 seconds to 1 second. For a demonstration of this see this tweet by contributor Will Smith. F# tooling: In-memory cross-project referencing! In F# 6, we made working between F# and C# projects simpler and more reliable through "In-memory cross-project referencing" from F# to C#. 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. F# tooling: .NET Core the default for scripting If you open or execute an F# Script (.fsx) 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. To enable .NET Framework scripting, use Tools -> Options -> F# Tools -> F# Interactive and set Use .NET Core Scripting to false and restart the F# Interactive window. This setting affects both script editing and script execution. 64-bit scripting is now also the default. To enable 32-bit execution for .NET Framework scripting, also set 64-bit F# Interactive to false. There is no 32-bit option for .NET Core scripting. F# tooling: F# scripts now respect global.json If you execute a script using dotnet fsi in a directory containing a global.json 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. For example, assume is a script is in a directory with the following global.json specifying a .NET SDK version policy: { "sdk": { "version": "5.0.200", "rollForward": "minor" } } This is a powerful feature that lets you "lock down" the SDK used to compile, analyse and execute your scripts. * If you now execute the script using dotnet fsi, 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. * Visual Studio and other IDEs will respect this setting when you are editing script. * When you start or reset the F# Interactive evaluation window in Visual Studio, the SDK choice is delayed until you first use "Send to Interactive" (Alt-Enter) from the script. At this point, the SDK chosen will the one used for editing and executing the script. On Linux and other UNIX systems you can combine a global.json with a shebang with a language version for direct execution of the script. A simple shebang for script.fsx is: #!/usr/bin/env -S dotnet fsi printfn "Hello, world" The script can be executed directly with script.fsx. You can combine this with a specific, non-default language version like this: #!/usr/bin/env -S dotnet fsi --langversion:5.0 Note that this setting will be ignored by editing tools, which will analyse the script assuming latest language version. F# tooling: .NET Interactive in Visual Studio Code and Visual Studio! .NET Interactive Notebooks 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. Also just announced is a Notebook Editor extension for Visual Studio 2022. Making F# simpler to learn: Code Examples! 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: * All functions in the List, Array, Seq and Map modules now have code examples. * Functions and methods in advanced modules such as Quotations now have examples. You can contribute to this initiative via this GitHub issue. General Improvements in .NET 6 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 .NET 6 Release Candidate 1 and previous release announcements. * Source build, 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. * Profile-guided optimization, 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. * Dynamic PGO, a mirror image of PGO, integrated with the RyuJIT .NET just-in-time compiler. Performance is improved. * Crossgen2, to generate and optimize code via ahead-of-time compilation, is now enabled by default when publishing ReadyToRun images. * Intel Control Enforcement Technology (CET), available in some new Intel and AMD processors to protect against common types of attacks involving control-flow hijacking. * HTTP/3, previewed in .NET 6, solves functional and performance challenges with previous versions of HTTP. * W^X, a security mitigation to block attack paths by disallowing memory pages to be writable and executable at the same time. Other improvements in .NET 6 include: * Interface casting performance has been improved by 16 percent to 38 percent. * Code generation has been improved in RyuJIT via multiple changes, to make the process more efficient or resulting code run faster. * Single-file bundles now support compression. * Single-file application publishing improvements including improved analysis to allow for custom warnings. * Enhanced date, time, and time zone support. * Significantly improved FileStream performance on Windows. * OpenSSL 3 support has been added for cryptography on Linux. * OpenTelemetry Metrics API support has been added. OpenTelemetry, which has been supported in recent .NET versions, promotes observability. * WebSocket compression for libraries reduces the amount of data transmitted over a network. * Package validation tools enable NuGet library developers to validate that packages are consistent and well-formed. * TLS support for DirectoryServices.Protocols. * Native memory allocation APIs. General Improvements in Visual Studio 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: * Visual Studio 2022 on Windows is now a 64-bit application. This means you can open, edit, run, and debug even the biggest and most complex solutions without running out of memory. * Find in Files is faster. Find in Files is now as much as 3x faster when searching large solutions such as Orchard Core. * Multi-repo support with Git in the IDE. If you'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. * Personalization improvements. For example, Visual Studio 2022 offers you the ability to sync with your Windows theme - if you've enabled the "night light" feature there, Visual Studio uses it, too. What's next Now that F# 6 is released, we're moving our focus to a few areas: 1. Simplifying the F# learning experience 2. Continuing to modernize the F# language service implementation 3. Planning for the next F# version Cheers, and happy F# coding! Thanks and Acknowledgments! 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're proud to be a contributing part of this community. Many people have contributed directly and indirectly to F# 6, including all who have contributed to the F# Language Design Process through fsharp/fslang-suggestions and fsharp/fslang-design repositories. Robert Peele developed TaskBuilder.fs and Nino Floris developed Ply. Will Smith, Kevin Ransom, Vlad Zarytovskii, Phillip Carter, Don Syme, Brett V. Forsgren contributed directly at Microsoft under the guidance of Jon Sequeira and Tim Heuer. Eugene Auduchinok made 41 PRs to the F# core implementation, including significant improvements to error recovery. Florian Verdonck made 24 PRs, including improved source trees for the Fantomas source code formatter. Hadrian Tang made 22 PRs, including several of the language features and simplifications outlined in this blog post. GitHub user kerams made 13 pull requests, including support for SkipLocalsInit and performance improvements. Scott Hutchinson made 9 PRs, Goswin Rothenthal made 7 PRs, Ryan Coy made 6 PRs, Victor Baybekov made 5 PRs, 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. Other direct contributors to the dotnet/fsharp repository in the F# 6.0 time period include forki, smoothdevelopers, cristianosuzuki77, ErikSchierboom, jonfortescue, teo-tsirpanis, MaxWilson, mmitche, DedSec256, uxsoft, Swoorup, En3Tho, 0x6a62, uweigand, MecuStefan, JYCabello, Yatao Li, amieres, chillitom, Daniel-Svensson, Krzysztof-Cieslak, thinkbeforecoding, abelbraaksma and ShalokShalom. Many other people are contributing to the rollout of F# 6 and .NET 6 in Fable, Ionide, Bolero, FSharp.Data, Giraffe, Saturn, SAFE Stack, WebSharper, FsCheck, DiffSharp, Fantomas and other community-delivered technologies. Contributor Showcase In this and future announcements we will highlight some of the individuals who contribute to F#. This text is written in the contributors' own words: I'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 - when I'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. Contributor photo I'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 comment by Charles Roddie 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'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's huge array of libraries, teaming up with [WhiteBlackGoose] (https://github.com/ WhiteBlackGoose). Much thanks to Don Syme for creating such an amazing language with simple syntax and great interoperability, and to the F# Discord 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! Hadrian Tang photo [png] Kathleen Dollard Principal Program Manager, .NET Follow Posted in .NET F#Tagged F# F# 6 Read next Contributing to .NET MAUI Community Toolkit Announcing the new process for contributing to the .NET MAUI Community Toolkit [png] Brandon Minnick October 15, 2021 0 comment .NET Framework October 2021 Security and Quality Rollup Yesterday, we released the October 2021 Security and Quality Rollup for .NET Framework. Security The October Security and Quality Rollup does not contain any new ... [png] Tara Overfield October 13, 2021 0 comment 5 comments Leave a commentCancel reply Log in to join the discussion. * [png] Ayman Elfaki October 19, 2021 12:21 pm collapse this comment Thank you for the awesome work. What are the plans for code formating and code lens support in Visual Studio? Log in to Reply + [png] Kathleen DollardMicrosoft employee October 19, 2021 3:11 pm collapse this comment Can you clarify what you mean by CodeLens? The C#/VB style member headers or the preview F# feature that shows signatures at the end of the line (in preview and rather un-pretty sometimes). Also, what kind of code formatting do you want to see - there's a pretty broad range. Log in to Reply * [png] Tony Henrique October 19, 2021 12:49 pm collapse this comment Very cool! Great new features and good to see going in this direction of be more friendly for newcomers. Log in to Reply * [png] Alex Corrado October 19, 2021 12:51 pm collapse this comment Install the latest .NET 6 SDK RC2 preview The download at that link says it has F# 5.0 EDIT: Despite what it says on that page, it does indeed seem to install F# 6.0 Log in to Reply + [png] Kathleen DollardMicrosoft employee October 19, 2021 3:11 pm collapse this comment Yes, this is an error we are in the process of fixing. Log in to Reply Relevant Links .NET Download .NET Hello World .NET Meetup Events .NET Documentation .NET API Browser .NET SDKs .NET Application Architecture Guides Web apps with ASP.NET Core Mobile apps with Xamarin.Forms Microservices with Docker Containers Modernizing existing .NET apps to the cloud Archive October 2021 September 2021 August 2021 July 2021 June 2021 May 2021 April 2021 March 2021 February 2021 January 2021 December 2020 November 2020 October 2020 September 2020 August 2020 July 2020 June 2020 May 2020 April 2020 March 2020 February 2020 January 2020 December 2019 November 2019 October 2019 September 2019 August 2019 July 2019 June 2019 May 2019 April 2019 March 2019 February 2019 January 2019 December 2018 November 2018 October 2018 September 2018 August 2018 July 2018 June 2018 May 2018 April 2018 March 2018 February 2018 January 2018 December 2017 November 2017 October 2017 September 2017 August 2017 July 2017 June 2017 May 2017 April 2017 March 2017 February 2017 January 2017 December 2016 November 2016 October 2016 September 2016 August 2016 July 2016 June 2016 May 2016 April 2016 March 2016 February 2016 January 2016 December 2015 November 2015 October 2015 September 2015 August 2015 July 2015 May 2015 April 2015 March 2015 February 2015 January 2015 December 2014 November 2014 October 2014 September 2014 August 2014 July 2014 June 2014 May 2014 April 2014 March 2014 February 2014 January 2014 December 2013 November 2013 October 2013 September 2013 August 2013 July 2013 June 2013 May 2013 April 2013 February 2013 January 2013 December 2012 November 2012 October 2012 September 2012 August 2012 July 2012 June 2012 May 2012 April 2012 March 2012 February 2012 October 2011 September 2011 June 2011 April 2011 November 2010 September 2010 June 2010 May 2010 April 2010 March 2010 February 2010 December 2009 November 2009 October 2009 September 2009 August 2009 July 2009 June 2009 May 2009 April 2009 March 2009 February 2009 January 2009 November 2008 May 2007 March 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 June 2006 April 2006 March 2006 February 2006 January 2006 October 2005 July 2005 May 2005 December 2004 November 2004 September 2004 June 2004 Topics .NET .NET Core .NET Framework Entity Framework C# ASP.NET ML.NET WPF Performance Machine Learning F# Visual Studio AI Machine Learning Containers Security .NET Internals WinForms .NET MAUI Conversations Azure Game Development Show dotnet Lifecycle Debugging Docker Maoni Async Concurrency GC TPL Apache Big Data Spark for .NET Visual Basic Static Analysis IoT SQL Server LOH XAML Stay informed Login Insert/edit link Close Enter the destination URL URL [ ] Link Text [ ] [ ] Open link in a new tab Or link to existing content Search [ ] No search term specified. Showing recent items. Search or use up and down arrow keys to select an item. Cancel [Add Link] Code Block x Paste your code snippet [ ] Cancel Ok What's new * Surface Pro 8 * Surface Laptop Studio * Surface Pro X * Surface Go 3 * Surface Duo 2 * Surface Pro 7+ * Windows 11 apps * HoloLens 2 Microsoft Store * Account profile * Download Center * Microsoft Store support * Returns * Order tracking * Virtual workshops and training * Microsoft Store Promise * Flexible Payments Education * Microsoft in education * Office for students * Office 365 for schools * Deals for students & parents * Microsoft Azure in education Enterprise * Azure * AppSource * Automotive * Government * Healthcare * Manufacturing * Financial services * Retail Developer * Microsoft Visual Studio * Windows Dev Center * Developer Center * Microsoft developer program * Channel 9 * Microsoft 365 Dev Center * Microsoft 365 Developer Program * Microsoft Garage Company * Careers * About Microsoft * Company news * Privacy at Microsoft * Investors * Diversity and inclusion * Accessibility * Security English (United States) * Sitemap * Contact Microsoft * Privacy * Manage cookies * Terms of use * Trademarks * Safety & eco * About our ads * (c) Microsoft 2021