4

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?

Abel
  • 56,041
  • 24
  • 146
  • 247

1 Answers1

8

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#?

Community
  • 1
  • 1
Be Brave Be Like Ukraine
  • 7,596
  • 3
  • 42
  • 66
  • Yes, this is indeed the logical thing to do (as I briefly mentioned in the last para). I was mainly surprised by the fact that it compiles, until you actually use the pattern. What does it compile to and/or is it possible to use the compiled multi-case active pattern, perhaps outside the context of pattern matching? – Abel May 17 '15 at 13:35
  • PS: I didn't find the linked question earlier because I googled with the error code `FS0722`, the linked question has the same description of the error, but a different code. – Abel May 17 '15 at 13:36
  • I did not check exactly what IL is generated, but the linked answers seem to be logical: a non-partial Active Pattern function is called just once, and there's no way to bind parameters at that moment. I have already edited the linked Q so that someone else in the future could find it. – Be Brave Be Like Ukraine May 17 '15 at 17:41