How to pattern-match when something is NOT of a particular type
We're all used to pattern-matching for cases when something is a particular type, e.g.,
match x with
| Y(x) :: tail -> ... // assumes List.head(x) is of type Y(x)
开发者_如何学Python
But how can can I match the case when something is not of a particular type? E.g.,
match x with
| Not Y(_) :: tail -> ... // List.head(x) is definitely not a Y
Thanks!
While there is no direct support for Not
you can use a partial active pattern.
type Color = | Red | Green | Blue
let (|NotRed|_|) = function
| Red -> None
| color -> Some color
let rec print = function
| (NotRed head) :: tail ->
printfn "%A is Not Red" head
print tail
| _ :: tail -> print tail
| _ -> ()
print [Red; Green; Blue]
output
Green is Not Red
Blue is Not Red
I think the usual way to deal with this is to first write a clause that explicitly excludes the cases you don't want. Then you can use _
to handle all remaining cases (You need to write some code for the case you want to exclude, but that needs to be written anyway to make the pattern matching complete):
match x with
| Y _ :: tail -> ()
| _ :: tail -> // List.head(x) is definitely not a Y
This definitely feels like a workaround, but I'm afraid that's the best you can do. If you wanted to exclude multiple cases, you can write something like:
match x with
| (Y _ | (Z (1 | 2 | 3 | 4)) :: tail -> ()
| _ :: tail -> // Excludes all "Y x" and "Z n when n \in 1,2,3,4"
Anyway, this is a very interesting question - I'm wondering if the language of patterns could be extended with some special pattern for expressing negation... Interestingly, this is not something that could be directly written using active patterns.
精彩评论