I came across an oddity in the F# pattern matching syntax today, which can lead to apparent failures in the exhaustivity check.
type Thing =
| This
| That
| Other
let useThing =
function
| This -> "A"
| That -> "A"
| That -> "B" // compiler complains
| Other -> "B"
In the above scenario the compiler helpfully tells me that the second That rule will never be matched. However, if I had tried to make the code a bit more compact and had written
let useThing =
function
| This | That -> "A"
| That | Other -> "B"
I do not get any help from the compiler. I think the reason is that | This | That ->. "A"
is not a shortcut for | This -> "A" | That -> "A"
, even though it looks very much like it is (and I've seen many code samples that treat it as such). Instead, from what I can find, the pipe symbol is used both to separate individual patterns, and also as OR pattern.
This is not a big issue for most DUs, but I encountered the problem when mapping a DU with a large number of cases into another DU with a small number of cases. My attempt to use the shortcut syntax caused a bug.
So my questions are:
For example, x* matches any number of x characters, [0-9]* matches any number of digits, and . * matches any number of anything. A regular expression pattern match succeeds if the pattern matches anywhere in the value being tested.
Regular programming languages make use of regular expressions (regex) for pattern matching. Pattern matching is used to determine whether source files of high-level languages are syntactically correct. It is also used to find and replace a matching pattern in a text or code with another text/code.
Regular expression pattern-matching can be performed with either a single character or a pattern of one or more characters in parentheses, called a character pattern. Metacharacters have special meanings, as described in the following table.
Your interpretation is correct.
By leaving out the actions for the first This
and second That
you are creating an OR pattern as described in Pattern Matching (F#)
To me this is slightly confusing, too, since the logical 'or' is || in F#.
And while it is easy to see the first bar as new alternative
and second bar as or
in your formatting it becomes less obvious in
let useThing =
function
| This
| That -> "A"
| That
| Other -> "B"
However the compiler can tell whether a whole pattern is useless but it cannot simplify a pattern.
That | Other
has a valid match and is therefore not redundant as considered by the compiler.
You can think of much more involved patterns where it would be not at all clear if parts can be left out or how to simplify them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With