diff --git a/docs/fsharp/language-reference/active-patterns.md b/docs/fsharp/language-reference/active-patterns.md
index 9302aab665882..cbc8ae04de099 100644
--- a/docs/fsharp/language-reference/active-patterns.md
+++ b/docs/fsharp/language-reference/active-patterns.md
@@ -18,7 +18,7 @@ let (|identifier|) [arguments] valueToMatch = expression
let (|identifier1|identifier2|...|) valueToMatch = expression
// Partial active pattern definition.
-// Uses a FSharp.Core.option<_> to represent if the type is satisfied at the call site.
+// Can use FSharp.Core.option<_>, FSharp.Core.voption<_> or bool to represent if the type is satisfied at the call site.
let (|identifier|_|) [arguments] valueToMatch = expression
```
@@ -132,9 +132,38 @@ Note however that only single-case active patterns can be parameterized.
[!code-fsharp[Main](~/samples/snippets/fsharp/lang-ref-2/snippet5008.fs)]
+## Return Type for Partial Active Patterns
+
+Partial active patterns return `Some ()` to indicate a match and `None` otherwise.
+
+Consider this match:
+
+```fsharp
+match key with
+| CaseInsensitive "foo" -> ...
+| CaseInsensitive "bar" -> ...
+```
+
+The partial active pattern for it would be:
+
+```fsharp
+let (|CaseInsensitive|_|) (pattern: string) (value: string) =
+ if String.Equals(value, pattern, StringComparison.OrdinalIgnoreCase) then
+ Some ()
+ else
+ None
+```
+
+Starting with F# 9, such patterns can also return `bool`:
+
+```fsharp
+let (|CaseInsensitive|_|) (pattern: string) (value: string) =
+ String.Equals(value, pattern, StringComparison.OrdinalIgnoreCase)
+```
+
## Struct Representations for Partial Active Patterns
-By default, partial active patterns return an `option` value, which will involve an allocation for the `Some` value on a successful match. Alternatively, you can use a [value option](value-options.md) as a return value through the use of the `Struct` attribute:
+By default, if a partial active pattern returns an `option`, this will involve an allocation for the `Some` value on a successful match. To avoid it, you can use a [value option](value-options.md) as a return value through the use of the `Struct` attribute:
```fsharp
open System
diff --git a/docs/fsharp/language-reference/attributes.md b/docs/fsharp/language-reference/attributes.md
index 69df5d0c80811..3abe48aa07a54 100644
--- a/docs/fsharp/language-reference/attributes.md
+++ b/docs/fsharp/language-reference/attributes.md
@@ -81,6 +81,82 @@ Although you do not usually need to specify the attribute target explicitly, val
[<``module``: MyCustomAttributeThatWorksOnModules>]
```
+
+
+
+ method |
+
+
+```fsharp
+[]
+let someFunction() = 42
+```
+
+ |
+
+
+ class |
+
+
+```fsharp
+[]
+type MyClass(myValue: int) =
+ member _.MyValue = myValue
+```
+
+ |
+
+
+ struct |
+
+
+```fsharp
+[]
+[]
+type MyStruct(myValue: int) =
+ member _.MyValue = myValue
+```
+
+ |
+
+
+ interface |
+
+
+```fsharp
+[]
+type MyInterface =
+ abstract member Prop: string
+```
+
+ |
+
+
+ enum |
+
+
+```fsharp
+[]
+type Color =
+ | Red = 0
+ | Green = 1
+ | Blue = 2
+```
+
+ |
+
+
+ constructor |
+
+
+```fsharp
+type MyClass(myValue: int) =
+ member _.MyValue = myValue
+
+ []
+ new () = MyClass 42
+```
+
|
diff --git a/docs/fsharp/language-reference/byrefs.md b/docs/fsharp/language-reference/byrefs.md
index a7311651787f6..fd1dfb27e125c 100644
--- a/docs/fsharp/language-reference/byrefs.md
+++ b/docs/fsharp/language-reference/byrefs.md
@@ -179,6 +179,8 @@ A "`byref`-like" struct in F# is a stack-bound value type. It is never allocated
* They cannot be static or instance members of a class or normal struct.
* They cannot be captured by any closure construct (`async` methods or lambda expressions).
* They cannot be used as a generic parameter.
+ * Starting with F# 9, this restriction is relaxed if the generic parameter is defined in C# using the allows ref struct anti-constraint. F# can instantiate such generics in types and methods with byref-like types. As a few examples, this affects BCL delegate types (`Action<>`, `Func<>`), interfaces (`IEnumerable<>`, `IComparable<>`) and generic arguments with a user-provided accumulator function (`String.string Create(int length, TState state, SpanAction action)`).
+ * It is impossible to author generic code supporting byref-like types in F#.
This last point is crucial for F# pipeline-style programming, as `|>` is a generic function that parameterizes its input types. This restriction may be relaxed for `|>` in the future, as it is inline and does not make any calls to non-inlined generic functions in its body.
diff --git a/docs/fsharp/language-reference/compiler-directives.md b/docs/fsharp/language-reference/compiler-directives.md
index c511c47a2b1fe..a94b560561768 100644
--- a/docs/fsharp/language-reference/compiler-directives.md
+++ b/docs/fsharp/language-reference/compiler-directives.md
@@ -23,7 +23,7 @@ The following table lists the preprocessor directives that are available in F#.
|`#else`|Supports conditional compilation. Marks a section of code to include if the symbol used with the previous `#if` is not defined.|
|`#endif`|Supports conditional compilation. Marks the end of a conditional section of code.|
|`#`[line] *int*,
`#`[line] *int* *string*,
`#`[line] *int* *verbatim-string*|Indicates the original source code line and file name, for debugging. This feature is provided for tools that generate F# source code.|
-|`#nowarn` *warningcode*|Disables a compiler warning or warnings. To disable a warning, find its number from the compiler output and include it in quotation marks. Omit the "FS" prefix. To disable multiple warning numbers on the same line, include each number in quotation marks, and separate each string by a space.
For example: `#nowarn "9" "40"`|
+|`#nowarn` *warningcode*|Disables a compiler warning or warnings. To disable multiple warning numbers on the same line, separate each string by a space.
For example: `#nowarn 9 42`|
The effect of disabling a warning applies to the entire file, including portions of the file that precede the directive.|
diff --git a/docs/fsharp/language-reference/computation-expressions.md b/docs/fsharp/language-reference/computation-expressions.md
index a583c7195c1f4..3989c89e8384c 100644
--- a/docs/fsharp/language-reference/computation-expressions.md
+++ b/docs/fsharp/language-reference/computation-expressions.md
@@ -440,7 +440,7 @@ You can define a custom operation on a computation expression and use a custom o
If you already have a builder class, its custom operations can be extended from outside of this builder class. Extensions must be declared in modules. Namespaces cannot contain extension members except in the same file and the same namespace declaration group where the type is defined.
-The following example shows the extension of the existing `FSharp.Linq.QueryBuilder` class.
+The following example shows the extensions of the existing `FSharp.Linq.QueryBuilder` class.
```fsharp
open System
@@ -448,9 +448,13 @@ open FSharp.Linq
type QueryBuilder with
- []
- member _.ExistsNot (source: QuerySource<'T, 'Q>, predicate) =
- System.Linq.Enumerable.Any (source.Source, Func<_,_>(predicate)) |> not
+ []
+ member _.any (source: QuerySource<'T, 'Q>, predicate) =
+ System.Linq.Enumerable.Any (source.Source, Func<_,_>(predicate))
+
+ [] // you can specify your own operation name in the constructor
+ member _.singleOrDefault (source: QuerySource<'T, 'Q>, predicate) =
+ System.Linq.Enumerable.SingleOrDefault (source.Source, Func<_,_>(predicate))
```
Custom operations can be overloaded. For more information, see [F# RFC FS-1056 - Allow overloads of custom keywords in computation expressions](https://github.com/fsharp/fslang-design/blob/main/FSharp-6.0/FS-1056-allow-custom-operation-overloads.md).
diff --git a/docs/fsharp/language-reference/discriminated-unions.md b/docs/fsharp/language-reference/discriminated-unions.md
index 7f241b3c5c95e..885849c153504 100644
--- a/docs/fsharp/language-reference/discriminated-unions.md
+++ b/docs/fsharp/language-reference/discriminated-unions.md
@@ -113,16 +113,17 @@ type SingleCase = Case of string
[]
type Multicase =
- | Case1 of Case1 : string
- | Case2 of Case2 : int
- | Case3 of Case3 : double
+ | Case1 of string
+ | Case2 of int
+ | Case3 of double
```
Because these are value types and not reference types, there are extra considerations compared with reference discriminated unions:
1. They are copied as value types and have value type semantics.
-2. You cannot use a recursive type definition with a multicase struct Discriminated Union.
-3. You must provide unique case names for a multicase struct Discriminated Union.
+2. You cannot use a recursive type definition with a multicase struct discriminated union.
+
+Before F# 9, there was a requirement for each case to specify a unique case name (within the union). Starting with F# 9, the limitation is lifted.
## Using Discriminated Unions Instead of Object Hierarchies
@@ -190,6 +191,23 @@ type Shape =
| Rectangle(l, w) -> printfn $"Rectangle with length %f{l} and width %f{w}"
```
+## `.Is*` properties on cases
+
+Since F# 9, discriminated unions expose auto-generated `.Is*` properties for each case, allowing you to check if a value is of a particular case.
+
+This is how it can be used:
+
+```fsharp
+type Contact =
+ | Email of address: string
+ | Phone of countryCode: int * number: string
+
+type Person = { name: string; contact: Contact }
+
+let canSendEmailTo person =
+ person.contact.IsEmail // .IsEmail is auto-generated
+```
+
## Common attributes
The following attributes are commonly seen in discriminated unions:
diff --git a/docs/fsharp/language-reference/fsharp-collection-types.md b/docs/fsharp/language-reference/fsharp-collection-types.md
index df65ed2649665..7f0d18fb077c2 100644
--- a/docs/fsharp/language-reference/fsharp-collection-types.md
+++ b/docs/fsharp/language-reference/fsharp-collection-types.md
@@ -97,6 +97,21 @@ This section compares the functions that are available on F# collection types. T
|partition|O(N)|O(N)|-|O(N)|O(N)|Splits the collection into two collections. The first collection contains the elements for which the given predicate returns `true`, and the second collection contains the elements for which the given predicate returns `false`.|
|permute|O(N)|O(N)|-|-|-|Returns an array with all elements permuted according to the specified permutation.|
|pick|O(N)|O(N)|O(N)|O(log(N))|-|Applies the given function to successive elements, returning the first result where the function returns Some. If the function never returns Some, `System.Collections.Generic.KeyNotFoundException` is raised.|
+|randomChoice|O(1)|O(1)|O(1)|-|-|Returns a random element from the given collection.|
+|randomChoiceBy|O(1)|O(1)|O(1)|-|-|Returns a random element from the given collection with the specified `randomizer` function.|
+|randomChoiceWith|O(1)|O(1)|O(1)|-|-|Returns a random element from the given collection with the specified `Random` instance.|
+|randomChoices|O(count)|O(count)|O(count)|-|-|Returns a collection of random elements from the given collection, each element can be selected multiple times.|
+|randomChoicesBy|O(count)|O(count)|O(count)|-|-|Returns a collection of random elements from the given collection with the specified `randomizer` function, each element can be selected multiple times.|
+|randomChoicesWith|O(count)|O(count)|O(count)|-|-|Returns a collection of random elements from the given collection with the specified `Random` instance, each element can be selected multiple times.|
+|randomSample|O(count)|O(count)|O(count)|-|-|Returns a random sample of elements from the given collection, each element can be selected only once.|
+|randomSampleBy|O(count)|O(count)|O(count)|-|-|Returns a random sample of elements from the given colleciton with the specified `randomizer` function, each element can be selected only once.|
+|randomSampleWith|O(count)|O(count)|O(count)|-|-|Returns a random sample of elements from the given collection with the specified `Random` instance, each element can be selected only once.|
+|randomShuffle|O(N)|O(N)|O(N)|-|-|Return a new collection shuffled in a random order.|
+|randomShuffleBy|O(N)|O(N)|O(N)|-|-|Return a new collection shuffled in a random order with the specified `randomizer` function.|
+|randomShuffleWith|O(N)|O(N)|O(N)|-|-|Return a new collection shuffled in a random order with the specified `Random` instance.|
+|randomShuffleInPlace|O(N)|-|-|-|-|Sorts input array in a random order by mutating the array in-place.|
+|randomShuffleInPlaceBy|O(N)|-|-|-|-|Sorts input array in a random order using the specified `randomizer` function by mutating the array in-place.|
+|randomShuffleInPlaceWith|O(N)|-|-|-|-|Sorts input array in a random order with the specified `Random` instance by mutating the array in-place.|
|readonly|-|-|O(N)|-|-|Creates a sequence object that delegates to the given sequence object. This operation ensures that a type cast can't rediscover and mutate the original sequence. For example, if given an array, the returned sequence will return the elements of the array, but you can't cast the returned sequence object to an array.|
|reduce|O(N)|O(N)|O(N)|-|-|Applies a function to each element of the collection, threading an accumulator argument through the computation. This function starts by applying the function to the first two elements, passes this result into the function along with the third element, and so on. The function returns the final result.|
|reduceBack|O(N)|O(N)|-|-|-|Applies a function to each element of the collection, threading an accumulator argument through the computation. If the input function is f and the elements are i0...iN, this function computes f i0 (...(f iN-1 iN)).|
diff --git a/docs/fsharp/tools/fsharp-interactive/index.md b/docs/fsharp/tools/fsharp-interactive/index.md
index 1ae6ff3de2bc9..dd30cb2813832 100644
--- a/docs/fsharp/tools/fsharp-interactive/index.md
+++ b/docs/fsharp/tools/fsharp-interactive/index.md
@@ -243,15 +243,17 @@ The `#r` and `#load` directives seen previously are only available in F# Interac
|`#help`|Displays information about available directives or documentation for specific functions.|
|`#I`|Specifies an assembly search path in quotation marks.|
|`#quit`|Terminates an F# Interactive session.|
-|`#time "on"` or `#time "off"`|By itself, `#time` toggles whether to display performance information. When it is `"on"`, F# Interactive measures real time, CPU time, and garbage collection information for each section of code that is interpreted and executed.|
+|`#time on` or `#time off`|By itself, `#time` toggles whether to display performance information. When it is `on`, F# Interactive measures real time, CPU time, and garbage collection information for each section of code that is interpreted and executed.|
[^1]: More about [F# Interactive extensions](https://aka.ms/dotnetdepmanager).
When you specify files or paths in F# Interactive, a string literal is expected. Therefore, files and paths must be in quotation marks, and the usual escape characters apply. You can use the `@` character to cause F# Interactive to interpret a string that contains a path as a verbatim string. This causes F# Interactive to ignore any escape characters.
+For other cases, quotation marks are optional, starting with F# 9.
+
### Extended #help directive
-The `#help` directive now supports displaying documentation for specific functions. You can pass the name of the function directly (without quotes) to retrieve details.
+The `#help` directive now supports displaying documentation for specific functions. You can pass the name of the function directly to retrieve details.
```fsharp
#help List.map;;