Description
There are a couple of ways in which it is possible to define "active patterns" that are (from the F# perspective) values, not functions. While the tooling treats them as active patterns, it is impossible to actually use them as patterns in any pattern-matching position.
Expected behavior
The compiler disallows defining a multi-case active pattern that is not a function:
let (|P|Q|) = Choice<unit, unit>.Choice1Of2 ()
// error FS1209: Active pattern '|P|Q|' is not a function
I would expect the same for single-case and partial active patterns.
Actual behavior
(|P|)
A value bound to what looks like a single-case active pattern name is actually compiled as a property with a getter (when a module-bound value):
let (|P|) = 3
// val (|P|) : int = 3
(|P|_|)
An option or value option value bound to a partial active pattern name is compiled to the exact same .NET method as it would be if it were defined as a function, but from the F# perspective it is a value (or a type function, even though you cannot give it explicit type arguments), not a function, although the tooling again treats it as an active pattern.
let (|P|_|) = None
// val (|P|_|) : 'a option
let (|P|_|) = ValueNone
// val (|P|_|) : 'a voption
Unfortunately, updating the compiler to disallow these scenarios would be a breaking change — someone could be passing values so defined around qua values (f (|P|)
, let r = (|P|) + (|Q|)
, etc.) — although I doubt anyone actually intentionally binds values to active pattern names like this in normal code.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status