2010-11-07 4 views
2

Код в следующем примере,F # соответствует шаблону из .Net констант

open System.Drawing 

let testColor c = 
    match c with 
    | Color.Black -> 1 
    | Color.White -> 0 
    | _ -> failwith "unexpected color" 

не компилируется. Ошибка Error 1 The field, constructor or member 'Black' is not defined.

Как сопоставить шаблон с .Net константами или перечислениями, начинающимися с заглавных букв?

Для чего это стоит, компилятор «Microsoft (R) F # 2.0 Interactive build 4.0.30319.1».

ответ

5

Вы не можете сопоставлять шаблону с произвольными значениями объекта. Используйте if then else или when условия:

let testColor c = 
    match c with 
    | c when c = Color.Black -> 1 
    | c when c = Color.White -> 0 
    | _ -> failwith "unexpected color" 
+0

идеальный ответ. Большое спасибо. –

11

Расширения на ответ, модельных матчи Брайана являются разными зверьми, чем заявления коммутатора. Они проверяют и разлагают структуру входных данных, а не равномерность тестового объекта. Но Active Patterns может быть вариантом, если разделение цветов на Black, White и Other будет часто использоваться во всей вашей программе. Для одноразовой «котельной» стоимости они позволяют вам определять структуру вокруг объекта, который вы манипулируете. Например,

open System.Drawing 
let (|Black|White|Other|) (color:Color) = 
    if color = Color.Black then Black 
    elif color = Color.White then White 
    else Other 

let testColor c = 
    match c with 
    | Black -> 1 
    | White -> 0 
    | Other -> failwith "unexpected color" 

Или, если вы также имеет дело только с черным и белым, но вы всегда хотите Black оценить как 1 и белые, чтобы оценить как 0, то вы можете использовать частичную Активную Patterns:

let (|KnownColor|_|) (color:Color) = 
    if color = Color.Black then Some(1) 
    elif color = Color.White then Some(0) 
    else None 

let testColor2 c = 
    match c with 
    | KnownColor i -> i 
    | _ -> failwith "unexpected color" 

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

let (|Equals|_|) (lhs) (rhs) = 
    if lhs = rhs then Some(lhs) else None 

let testColor3 c = 
    match c with 
    | Equals Color.Black _ -> 1 
    | Equals Color.White _ -> 0 
    | _ -> failwith "unexpected color" 

let testString c = 
    match c with 
    | Equals "Hi" _ -> 1 
    | Equals "Bye" _ -> 0 
    | _ -> failwith "unexpected string" 
+1

Впечатляющий. Я забыл об активных шаблонах, и ответ Брайана выполняет эту работу, но это очень хорошее объяснение того, как их использовать. –

Смежные вопросы