Как сопоставить с шаблоном, когда что-то НЕ относится к определенному типу - PullRequest
3 голосов
/ 22 февраля 2011

Мы все привыкли к сопоставлению с образцом в случаях, когда что-то представляет собой определенного типа, например,

match x with
| Y(x) :: tail -> ... // assumes List.head(x) is of type Y(x)

Но как я могу сопоставить случай, когда что-то не определенного типа? Например.,

match x with
| Not Y(_) :: tail -> ... // List.head(x) is definitely not a Y

Спасибо!

Ответы [ 2 ]

4 голосов
/ 22 февраля 2011

Хотя прямой поддержки Not нет, вы можете использовать частичный активный шаблон .

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]

выход

Green is Not Red
Blue is Not Red
4 голосов
/ 22 февраля 2011

Я думаю, что обычный способ справиться с этим - сначала написать предложение, которое явно исключает случаи, которые вам не нужны.Затем вы можете использовать _ для обработки всех оставшихся случаев (вам нужно написать некоторый код для случая, который вы хотите исключить, но его необходимо написать в любом случае, чтобы завершить сопоставление с образцом):

match x with
| Y _ :: tail -> ()
| _ :: tail -> // List.head(x) is definitely not a Y

Это определенно похоже на обходной путь, но я боюсь, что это лучшее, что вы можете сделать.Если вы хотите исключить несколько случаев, вы можете написать что-то вроде:

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"

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

...