2010-11-07 4 views
2

Le code dans l'exemple suivant,F # correspondance de motif de constantes .Net

open System.Drawing 

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

ne compile pas. L'erreur est Error 1 The field, constructor or member 'Black' is not defined.

Comment est-ce que le modèle correspond aux constantes .Net ou commençant par des majuscules?

Pour ce que ça vaut, le compilateur est "Microsoft (R) F # 2.0 Interactive build 4.0.30319.1".

Répondre

5

Vous ne pouvez pas faire correspondre le modèle à des valeurs d'objet arbitraires. Utilisez un if then else ou when conditions:

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

réponse parfaite. Merci beaucoup. –

11

expansion sur réponse, motif de matchs Brian sont une bête différente de celle des états de commutation. Ils testent et décomposent la structure d'une entrée plutôt que l'égalité des objets de test. Mais les motifs actifs peuvent être une option si la division des couleurs en noir, blanc et autre sera souvent utilisée tout au long de votre programme. Pour un coût ponctuel de «plaque chauffante», ils vous permettent de définir une structure autour de l'objet que vous manipulez. Par exemple,

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" 

Ou, si vous traitez également avec seulement noir et blanc, mais vous voulez toujours noir pour évaluer en 1 et blanc d'évaluer 0, vous pouvez utiliser des modèles actifs partiels:

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" 

Plus généralement, vous pouvez même simuler une instruction switch en utilisant un modèle générique actif partiel:

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

Impressionnant. J'ai oublié les motifs actifs, et la réponse de Brian fait le travail, mais c'est une très bonne explication de la façon de les utiliser. –

Questions connexes