Since I only found Japanese pages about this error, I figured, let's log it and ask here, since my Japanese is kinda rusty.
If I have the following FSharp active pattern (simplified example):
let (|InRange|OutOfRange|) from too =
function
| input when input >= from && input <= too -> InRange
| _ -> OutOfRange
It compiles perfectly and shows its type as:
val ( |InRange|OutOfRange| ) :
from:'a -> too:'a -> _arg1:'a -> Choice<unit,unit> when 'a : comparison
But when I try to use it, i.e. as follows, it throws an error:
let test i = match i with
| InRange 10 20 -> "in range"
| _ -> "out of range"
Throws: error FS0722: Only active patterns returning exactly one result may accept arguments
I can resolve it by turning it into two single-case parameterized active patterns, each returning None/Some(x), but I'm still wondering why I am not allowed doing so and/or whether there's syntax I can use that I am not aware of. I am also wondering why it compiles, but I cannot use it?
The simplest solution would be refactoring this into a partial active pattern:
let (|InRangeInclusive|_|) lo hi x =
if lo <= x && x <= hi then Some () else None
Then you may even combine them in something like this:
let test i = match i with
| InRangeInclusive 10 20 -> "in first range"
| InRangeInclusive 42 100 -> "in second range"
| _ -> "out of range"
Note, I took my liberty to give the pattern a better name, because those who would use your code may be confused about its behavior with corner cases.
I'm still wondering why I am not allowed doing so?
Why can't non-partial active patterns be parameterized in F#?
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