Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/core/whats-new/dotnet-7.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ C# 11 includes support for [generic math](../../standard/generics/math.md), raw

### F# 7

F# 7 continues the journey to make the language simpler and improve performance and interop with new C# features. For more information, see [Announcing F# 7](https://devblogs.microsoft.com/dotnet/announcing-fsharp-7/).
F# 7 continues the journey to make the language simpler and improve performance and interop with new C# features. For more information, see [What's new in F# 7](../../fsharp/whats-new/fsharp-7.md).

### .NET MAUI

Expand Down
4 changes: 4 additions & 0 deletions docs/core/whats-new/dotnet-8/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ For information about what's new in the .NET SDK, code analysis, and diagnostics

C# 12 shipped with the .NET 8 SDK. For more information, see [What's new in C# 12](../../../csharp/whats-new/csharp-12.md).

## F# 8

F# 8 focuses on making the language simpler, more consistent, and more performant. For more information, see [What's new in F# 8](../../../fsharp/whats-new/fsharp-8.md).

## Aspire

Aspire is an opinionated, cloud-ready stack for building observable, production ready, distributed applications.​ Aspire is delivered through a collection of NuGet packages that handle specific cloud-native concerns, and is available in preview for .NET 8. For more information, see [Aspire](/dotnet/aspire).
Expand Down
153 changes: 152 additions & 1 deletion docs/fsharp/whats-new/fsharp-7.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,158 @@ title: What's new in F# 7 - F# Guide
description: Find information on the new features available in F# 7.
ms.date: 11/17/2023
ms.topic: whats-new
ai-usage: ai-assisted
---
# What's new in F# 7

For information on F# 7, please see [Announcing F# 7](https://devblogs.microsoft.com/dotnet/announcing-fsharp-7).
F# 7 introduces several enhancements that improve interoperability with .NET, simplify common programming patterns, and enhance developer productivity. This article highlights the major changes in F# 7, developed in the [F# open source code repository](https://github.com/dotnet/fsharp).

F# 7 is available in .NET 7. You can download the latest .NET SDK from the [.NET downloads page](https://dotnet.microsoft.com/download).

## Static abstract members in interfaces

F# 7 adds support for static abstract members in interfaces, aligning with the feature introduced in C# 11 and .NET 7. This feature enables you to define interfaces that require implementing types to provide static members, which is particularly useful for generic math scenarios and other generic programming patterns.

You can define an interface with static abstract members using the `static abstract` keywords:

```fsharp
type IAddition<'T when 'T :> IAddition<'T>> =
static abstract member (+) : 'T * 'T -> 'T
static abstract member Zero : 'T
```

Types can implement these interfaces by providing the required static members:

```fsharp
type Number(value: int) =
member _.Value = value

interface IAddition<Number> with
static member (+) (x: Number, y: Number) =
Number(x.Value + y.Value)
static member Zero = Number(0)
```

This feature enables you to write generic algorithms that work across different types:

```fsharp
let inline addAll (items: 'T list) =
items |> List.fold (+) 'T.Zero
Comment on lines +41 to +42
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The syntax 'T.Zero is incorrect for accessing static members in F#. It should be ^T.Zero to properly reference the static member from the type parameter.

Suggested change
let inline addAll (items: 'T list) =
items |> List.fold (+) 'T.Zero
let inline addAll (items: ^T list) =
items |> List.fold (+) ^T.Zero

Copilot uses AI. Check for mistakes.

```

For more information, see [Interfaces](../language-reference/interfaces.md).

## Required members

F# 7 introduces support for required members, allowing you to mark properties and fields that must be initialized when creating an instance. This feature improves interoperability with C# 11's required members feature.

While F# has always encouraged initialization through primary constructors and immutable record types, this feature enables better interaction with .NET libraries that use required members:

```fsharp
[<Class>]
type Person() =
[<Required>]
member val FirstName = "" with get, set

[<Required>]
member val LastName = "" with get, set

member val MiddleName = "" with get, set
```

This improves the ability to consume and create types that are designed for use across both F# and C# codebases.

## Simplified SRTP syntax

Statically Resolved Type Parameters (SRTP) constraints have been simplified in F# 7. Previously, when using member constraints, you had to repeat the constraint even when calling simple members. Now you can use more concise syntax.

Before F# 7:

```fsharp
let inline add (x: ^T) (y: ^T) : ^T
when ^T : (static member (+) : ^T * ^T -> ^T) =
((^T) : (static member (+) : ^T * ^T -> ^T) (x, y))
```

Starting with F# 7, you can use the simpler syntax:

```fsharp
let inline add (x: ^T) (y: ^T) : ^T
when ^T : (static member (+) : ^T * ^T -> ^T) =
x + y
```

Additionally, you can now use `'a.Zero()` instead of having to repeat the constraint:

```fsharp
let inline sum (values: ^T list) : ^T
when ^T : (static member (+) : ^T * ^T -> ^T)
and ^T : (static member Zero : ^T) =
List.fold (+) (^T.Zero()) values
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The syntax ^T.Zero() is incorrect - Zero should be a property, not a method call. It should be ^T.Zero without parentheses.

Suggested change
List.fold (+) (^T.Zero()) values
List.fold (+) ^T.Zero values

Copilot uses AI. Check for mistakes.

```

This simplification makes SRTP constraints more approachable and reduces boilerplate code.

For more information, see [Statically Resolved Type Parameters](../language-reference/generics/statically-resolved-type-parameters.md).

## Nested record updates with copy-and-update expressions

F# 7 enhances copy-and-update expressions to support updating nested record fields directly. This feature allows for more concise syntax when working with deeply nested records.

Before F# 7, updating a nested field required multiple `with` expressions:

```fsharp
type SteeringWheel = { Type: string }
type CarInterior = { Steering: SteeringWheel; Seats: int }
type Car = { Interior: CarInterior; ExteriorColor: string option }

let updateCar car =
{ car with
Interior = { car.Interior with
Steering = { car.Interior.Steering with Type = "sport" }
Seats = 4 } }
```

Starting with F# 7, you can use dot notation to reach nested fields and update them directly:

```fsharp
let updateCar car =
{ car with
Interior.Steering.Type = "sport"
Interior.Seats = 4 }
```

This syntax eliminates the need for multiple nested `with` expressions while still allowing multiple fields at different levels of nesting to be updated in the same expression. The feature also works with anonymous records:

```fsharp
let updatedRecord =
{| car with
Interior.Seats = 4
Price = 35000 |}
```

For more information, see [Copy and Update Record Expressions](../language-reference/copy-and-update-record-expressions.md).

## Performance improvements

F# 7 includes several performance improvements:

- **Parallel type checking**: The compiler now uses graph-based type checking, enabling parallel type checking of files using a dependency graph. This significantly speeds up compilation for large projects.
- **Reduced memory consumption**: Various optimizations reduce memory usage during compilation and runtime.
- **Better cancellation handling**: Improved handling of canceled user actions provides better responsiveness in development environments.

## Tooling improvements

F# 7 brings significant improvements to the development experience in Visual Studio and other editors:

- **Enhanced code fixes**: Over 30 new code fixes for common development issues help streamline the coding process and reduce errors.
- **Improved IntelliSense**: Better type inference information and more accurate completions make it easier to discover and use APIs.
- **Performance improvements**: Faster response times for editor features like code completion, navigation, and refactoring.

These tooling enhancements lower the barrier of entry for new F# developers and improve productivity for experienced developers.

## See also

- [F# Language Reference](../language-reference/index.md)
- [What's new in F# 8](fsharp-8.md)
- [What's new in .NET 7](../../core/whats-new/dotnet-7.md)
139 changes: 138 additions & 1 deletion docs/fsharp/whats-new/fsharp-8.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,144 @@ title: What's new in F# 8 - F# Guide
description: Find information on the new features available in F# 8.
ms.date: 11/17/2023
ms.topic: whats-new
ai-usage: ai-assisted
---
# What's new in F# 8

For information on F# 8, please see [Announcing F# 8](https://devblogs.microsoft.com/dotnet/announcing-fsharp-8).
F# 8 focuses on making the language simpler, more consistent, and more performant. This article highlights the major changes in F# 8, developed in the [F# open source code repository](https://github.com/dotnet/fsharp).

F# 8 is available in .NET 8. You can download the latest .NET SDK from the [.NET downloads page](https://dotnet.microsoft.com/download).

## Simplified syntax

F# 8 introduces several syntax improvements that make code more concise and readable.

### Shortened lambda expressions

F# 8 introduces a shorthand syntax for lambda expressions using the underscore (`_`) character. Instead of writing `fun x -> x.Property`, you can now write `_.Property`:

Before F# 8:

```fsharp
let names = people |> List.map (fun person -> person.Name)
let ages = people |> List.map (fun person -> person.Age)
```

Starting with F# 8:

```fsharp
let names = people |> List.map _.Name
let ages = people |> List.map _.Age
```

This shorthand works for property access, method calls, and field access, making functional pipelines more concise and readable. The underscore represents the lambda parameter, and you can chain multiple accesses:

```fsharp
// Property access
customers |> List.map _.Address.City

// Method calls
numbers |> List.map _.ToString()

// Combining property access and method calls
items |> List.filter _.IsValid()
|> List.map _.Name.ToLower()
```

### Nested record field updates

Building on the F# 7 feature, F# 8 continues to improve copy-and-update expressions for nested records. You can update deeply nested record fields using dot notation:

```fsharp
type Address = { Street: string; City: string; PostalCode: string }
type Person = { Name: string; Address: Address }
type Company = { Name: string; CEO: Person }

let company =
{ Name = "Contoso"
CEO = { Name = "Alice"
Address = { Street = "123 Main St"
City = "Seattle"
PostalCode = "98101" } } }

// Update nested fields concisely
let updatedCompany =
{ company with CEO.Address.City = "Portland" }
```

This syntax eliminates deeply nested `with` expressions and makes record updates more intuitive.

## Computation expressions

### `while!` in computation expressions

F# 8 introduces the `while!` keyword, which allows you to use asynchronous or computation expression operations directly in while loops. This reduces boilerplate and makes async code more readable.

Before F# 8:

```fsharp
let processStream (stream: Stream) = async {
let buffer = Array.zeroCreate 1024
let mutable continueReading = true
while continueReading do
let! bytesRead = stream.AsyncRead(buffer, 0, buffer.Length)
if bytesRead = 0 then
continueReading <- false
else
// Process buffer
processBuffer buffer bytesRead
}
```

Starting with F# 8:

```fsharp
let processStream (stream: Stream) = async {
let buffer = Array.zeroCreate 1024
while! stream.AsyncRead(buffer, 0, buffer.Length) do
// Process buffer
processBuffer buffer bytesRead
Comment on lines +100 to +102
Copy link

Copilot AI Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable bytesRead is referenced but not defined in the while! example. The while! condition returns the bytes read, but it's not captured in a variable that can be used in the loop body.

Suggested change
while! stream.AsyncRead(buffer, 0, buffer.Length) do
// Process buffer
processBuffer buffer bytesRead
let rec loop () = async {
let! bytesRead = stream.AsyncRead(buffer, 0, buffer.Length)
if bytesRead <> 0 then
// Process buffer
processBuffer buffer bytesRead
return! loop ()
else
return ()
}
do! loop ()

Copilot uses AI. Check for mistakes.

}
```

The `while!` keyword automatically handles the computation expression binding, making the code more concise and eliminating the need for manual state management.

## Enhanced pattern matching

F# 8 includes improvements to pattern matching that enhance code clarity and reduce verbosity. These improvements make it easier to work with complex data structures and reduce the need for nested match expressions.

## Numeric literals

F# 8 allows you to use more flexible expressions for numeric literals. The compiler evaluates these expressions at compile time, enabling clearer code when working with numeric constants:

```fsharp
// You can now use expressions in numeric literals
let kilobyte = 1024
let megabyte = 1024 * kilobyte
let gigabyte = 1024 * megabyte

// This is evaluated at compile time
let bufferSize = 64 * 1024 // 64 KB
```

## Performance improvements

F# 8 includes various performance optimizations:

- **Faster compilation**: Improvements to the type checker and compiler infrastructure reduce build times for large projects.
- **Better code generation**: Enhanced optimization passes produce more efficient IL code.
- **Reduced allocations**: Several core library functions now allocate less memory, improving performance in allocation-heavy scenarios.

## Tooling enhancements

F# 8 brings improvements to the development experience:

- **Better error messages**: More helpful and actionable compiler errors and warnings guide you toward correct code.
- **Improved IDE support**: Enhanced IntelliSense, code completion, and tooltips in Visual Studio and Visual Studio Code.
- **Faster editing experience**: Reduced latency for common IDE operations like go-to-definition and find-all-references.

## See also

- [F# Language Reference](../language-reference/index.md)
- [What's new in F# 9](fsharp-9.md)
- [What's new in .NET 8](../../core/whats-new/dotnet-8/overview.md)