Precision: Constructor arguments may only be used in the arm for that constructor.
Exhaustiveness: Every pattern[0] is handled by an arm.
Co-exhaustiveness: Every arm handles at least one pattern.
So, in particular:
Using constructor arguments in the wrong arm is an error.
Inexhaustive matches are errors or warnings.
Redundant matches are errors or warnings.
The article’s code achieves none of these.
Footnotes:
[0] A pattern is either a free variable or a constructor applied to patterns. It matters not whether the pattern appears syntactically in an arm’s left-hand side in the program text.
As a OCaml programmer I am a bit surprised why you would declare the functions with type annotations that require it to be only for specific 'a - it makes it the code more verbose and less useful.
Not entirely unrelated: type annotations in ML are kind of ugly when you think about how nice it is in Haskell. I’ve run across the pattern
let foo : string -> 'a -> int = fun a b -> ...
Which to my surprise is actually quite bearable I think.
The point to pattern matching is threefold:
So, in particular:
The article’s code achieves none of these.
Footnotes:
[0] A pattern is either a free variable or a constructor applied to patterns. It matters not whether the pattern appears syntactically in an arm’s left-hand side in the program text.
As a OCaml programmer I am a bit surprised why you would declare the functions with type annotations that require it to be only for specific
'a- it makes it the code more verbose and less useful.Not entirely unrelated: type annotations in ML are kind of ugly when you think about how nice it is in Haskell. I’ve run across the pattern
Which to my surprise is actually quite bearable I think.