Многопараметризованные активные шаблоны, возвращающие ошибку FS0722 только активные шаблоны, возвращающие ровно один результат, могут принимать аргументы


Поскольку я нашел только японские страницы об этой ошибке, я решил, что давайте зарегистрируем ее и спросим здесь, поскольку мой японский немного ржавый.

Если у меня есть следующий активный шаблон FSharp (упрощенный пример):

let (|InRange|OutOfRange|) from too =
    function
    | input when input >= from && input <= too -> InRange
    | _ -> OutOfRange

Он прекрасно компилируется и показывает свой тип как:

val ( |InRange|OutOfRange| ) :
  from:'a -> too:'a -> _arg1:'a -> Choice<unit,unit> when 'a : comparison

Но когда я пытаюсь использовать его, то есть следующим образом, он выдает ошибку:

let test i = match i with
             | InRange 10 20 -> "in range"
             | _ -> "out of range"

Throws: error FS0722: только активные шаблоны, возвращающие ровно один результат, могут принимать аргументы

I можно решить его, превратив его в два одинарных параметризованных активных паттерна, каждый из которых возвращает None/Some (x), но я все еще задаюсь вопросом, почему мне это не разрешено и/или есть ли синтаксис, который я могу использовать, о котором я не знаю. Мне также интересно, почему он компилируется, но я не могу его использовать?

1 3

1 ответ:

Самым простым решением будет рефакторинг этого в частичный активный шаблон :

let (|InRangeInclusive|_|) lo hi x =
    if lo <= x && x <= hi then Some () else None

Тогда вы можете даже объединить их в нечто подобное:

let test i = match i with
         | InRangeInclusive 10 20 -> "in first range"
         | InRangeInclusive 42 100 -> "in second range"
         | _ -> "out of range"
Обратите внимание, я взял на себя смелость дать шаблону лучшее название, потому что те, кто будет использовать ваш код, могут путать его поведение с угловыми случаями.

я все еще удивляюсь, почему мне это не разрешено ?

Почему неполные активные паттерны не могут быть параметризованный в F#?