Active patterns are a really nice feature but I'm confused about the method for specifying a partial active pattern with multiple choices. It seems strange that the required approach is to have multiple declarations, one for each case, when this is not how
it is done for a standard active pattern.

To give an example, consider the following:

let (|One|Two|) n =
if n = 1 then One
elif n = 2 then Two
else failwith "Not one or two"
let test x =
match x with
| One -> printfn "one"
| Two -> printfn "two"

Currently (|One|Two|) effectively returns a member of the implicitly defined union type equivalent to

type Tmp = One | Two

So far, this is clear. Now imagine the behaviour of raising an exception in the other cases becomes unhelpful to the rest of the program and we wish to make the pattern partial. I would expect to be able to write:

let (|One|Two|_|) n =
if n = 1 then Some One
elif n = 2 then Some Two
else None

where the active pattern is now a function returning Option<Tmp>. The pattern match can perform the option type unwrapping so that the following would be effectively matching against Some One, Some Two, None but we can write One, Two, _ instead for
convenience.

let test x =
match x with
| One -> printfn "one"
| Two -> printfn "two"
| _ -> printfn "other"

Instead, it seems that we must write:

let (|One|_|) n =
if n = 1 then Some ()
else None
let (|Two|_|) n =
if n = 2 then Some ()
else None

which seems clumsy and appears to encourage accidentally writing disjoint or overlapping matches that would be vulnerable to reordering the match cases.

I note that it is simple enough to rewrite my desired multiple case partial active pattern like the following:

type Tmp = One | Two | Underscore
let onetwo n =
if n = 1 then One
elif n = 2 then Two
else Underscore
let test x =
match onetwo x with
| One -> printfn "one"
| Two -> printfn "two"
| _ -> printfn "other"

as is the case for every active pattern, but that isn't really an answer.

I assume that it is implemented like this for one of two reasons:

- Having different declarations for partial patterns gives a lot more flexibility
- It isn't as simple to unwrap the option type as I think for an active pattern

Can anyone enlighten me on this subject?