Skip to content
Merged
Changes from 2 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
62 changes: 59 additions & 3 deletions docs/fsharp/language-reference/pattern-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,29 @@

## Patterns That Have Type Annotations

Patterns can have type annotations. These behave like other type annotations and guide inference like other type annotations. Parentheses are required around type annotations in patterns. The following code shows a pattern that has a type annotation.
Patterns can have type annotations. These behave like other type annotations and guide inference like other type annotations. Parentheses are required around type annotations in patterns.

Check failure on line 187 in docs/fsharp/language-reference/pattern-matching.md

View workflow job for this annotation

GitHub Actions / lint

Trailing spaces

docs/fsharp/language-reference/pattern-matching.md:187:188 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md009.md

Check failure on line 187 in docs/fsharp/language-reference/pattern-matching.md

View workflow job for this annotation

GitHub Actions / lint

Trailing spaces

docs/fsharp/language-reference/pattern-matching.md:187:188 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md009.md

A pattern with a type annotation uses the syntax `pattern : type` and provides **compile-time type information** to the type checker. This is purely a static type annotation that helps with type inference - it doesn't perform any runtime type checking or conversion. The compiler uses this information during compilation to determine the type of the pattern variable.

The following code shows a pattern that has a type annotation:

[!code-fsharp[Main](~/samples/snippets/fsharp/lang-ref-2/snippet4815.fs)]

In this example, `(var1 : int)` tells the compiler that `var1` is of type `int`. This is resolved at compile time, and the generated code treats `var1` as an integer throughout the match expression. This pattern will match any integer value and bind it to `var1`.

**Key characteristics:**
- Uses the syntax `pattern : type` (with a single colon)

Check failure on line 198 in docs/fsharp/language-reference/pattern-matching.md

View workflow job for this annotation

GitHub Actions / lint

Lists should be surrounded by blank lines

docs/fsharp/language-reference/pattern-matching.md:198 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Uses the syntax `pattern : t..."] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md032.md

Check failure on line 198 in docs/fsharp/language-reference/pattern-matching.md

View workflow job for this annotation

GitHub Actions / lint

Lists should be surrounded by blank lines

docs/fsharp/language-reference/pattern-matching.md:198 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Uses the syntax `pattern : t..."] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md032.md
- Resolved at **compile time** - provides type information to the type checker
- Does not perform runtime type testing
- Used for type inference and to guide the compiler

## Type Test Pattern

The type test pattern is used to match the input against a type. If the input type is a match to (or a derived type of) the type specified in the pattern, the match succeeds.
The type test pattern is used to match the input against a type **at runtime**. If the input type is a match to (or a derived type of) the type specified in the pattern, the match succeeds.

A type test pattern uses the syntax `:? type` and performs **runtime type checking**, similar to the `is` or `as` operators in C#. This pattern tests whether a value is of a specific type during program execution, making it useful when working with inheritance hierarchies or interface implementations.

The following example demonstrates the type test pattern.
The following example demonstrates the type test pattern:

[!code-fsharp[Main](~/samples/snippets/fsharp/lang-ref-2/snippet4816.fs)]

Expand All @@ -210,6 +224,48 @@
| _ -> ()
```

**Key characteristics:**
- Uses the syntax `:? type` or `:? type as identifier` (with a question mark)

Check failure on line 228 in docs/fsharp/language-reference/pattern-matching.md

View workflow job for this annotation

GitHub Actions / lint

Lists should be surrounded by blank lines

docs/fsharp/language-reference/pattern-matching.md:228 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Uses the syntax `:? type` or..."] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md032.md

Check failure on line 228 in docs/fsharp/language-reference/pattern-matching.md

View workflow job for this annotation

GitHub Actions / lint

Lists should be surrounded by blank lines

docs/fsharp/language-reference/pattern-matching.md:228 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Uses the syntax `:? type` or..."] https://github.com/DavidAnson/markdownlint/blob/v0.38.0/doc/md032.md
- Resolved at **runtime** - performs actual type checking during execution
- Tests if a value is an instance of a specific type or its derived types
- Commonly used with inheritance hierarchies and polymorphic types
- Similar to C#'s `is` operator or `as` operator

### Contrasting Type Annotations and Type Test Patterns

While both patterns involve types, they serve very different purposes:

| Feature | Type Annotation Pattern (`pattern : type`) | Type Test Pattern (`:? type`) |
|---------|-------------------------------------------|-------------------------------|
| **Syntax** | Single colon: `a : int` | Colon with question mark: `:? Button` |
| **When resolved** | Compile time | Runtime |
| **Purpose** | Guides type inference | Tests actual type of value |
| **Use case** | Helping the compiler understand types | Checking runtime types in inheritance hierarchies |
| **Equivalent in C#** | Type annotations in switch patterns | `is` or `as` operators |

**Example showing the difference:**

```fsharp
// Type annotation pattern - compile time
let detect1 x =
match x with
| 1 -> printfn "Found a 1!"
| (var1 : int) -> printfn "%d" var1
// The ': int' tells the compiler var1 is an int
// Everything is resolved at compile time
// Type test pattern - runtime
type A() = class end
type B() = inherit A()
let test (a: A) =
match a with
| :? B -> printfn "Runtime check: it's a B"
| _ -> printfn "Runtime check: it's not a B"
// The ':? B' performs a runtime type check
// The actual type is tested during execution
```

## Null Pattern

The null pattern matches the null value that can appear when you are working with types that allow a null value. Null patterns are frequently used when interoperating with .NET Framework code. For example, the return value of a .NET API might be the input to a `match` expression. You can control program flow based on whether the return value is null, and also on other characteristics of the returned value. You can use the null pattern to prevent null values from propagating to the rest of your program.
Expand Down
Loading