let fn x =
match x with
| { Foo = bar } when bar < 0 -> bar
| _ -> failwith "bar >= 0"
As to why this is the case, it’s due first to the fact that the = is an equality / assignment. If you provide a value, it checks that the value matches. If a label is provided, the label is assigned the value. Allowing <, >, etc. would break this operation.
Secondly, it’s due to F#'s history as an OCaml for .NET. Since OCaml uses when to perform additional conditional checks, so does F#. The pattern match is intended to exactly match a data structure. The when allows you to use what you matched or external values in considering a result. For example, suppose you accepted an x and a y and wanted to return bar only if y < 0:
let fn x y =
match x with
| { Foo = bar } when y < 0 -> bar
| { Foo = bar } -> failwith "y was >= 0"
I think there may be multiple issues at play here. One issue is possibly confusion about | { Foo = 0 } in a match. The = at that point is not a comparison - it’s part of a “record pattern”. If you look at the Pattern Matching docs, you’ll see that each case of a pattern match is | pattern [ when condition ] -> result-expression : so you match a pattern (and optionally a condition, which @panesofglass showed nicely).
One type of pattern is a “Record pattern”, which is { identifierN = patternN } - so you setup an identifier, and a “sub pattern” that is matching. With {Foo = 0}, this is a record pattern containing a “Constant pattern” of 0, not a comparison for equality to 0.
This is more obvious if you nest even more patterns - for example, you can nest an OR pattern:
match foo with
| { Foo = 10|12} -> doSomething()
Here, the pattern is an OR pattern, with each sub pattern being a constant pattern.
If you go through the full list of patterns, you’ll see that no pattern has < as part of it’s syntax - there is no “comparison pattern”. Instead, you use a “Variable pattern” and then the optional conditional, ie: | { Foo = bar } when bar < 0.
Thank you to both of you guys. It is much much clearer now! Funny that even in the case of Foo = 10 that it’s not really even checking for equality. It’s using a constant pattern against the identifier to check equality.