2014-07-19 3 views
0

J'ai une fonction getFullFitnessF correspondance # modèle à une gamme de numéros

let getFullFitness population = 
    ResizeArray(population |> Seq.map snd) |> Seq.sum 

et je correspondance de motif dans la fonction RealTick

let realTick population = 
    match(getFullfitness population) with 
    |(50) -> population 
    | _ -> childGeneration population 

La question est sur la ligne | (50) -> Population . Puisque getFullFitness renvoie une somme entière, comment puis-je faire correspondre des valeurs comprises entre 0 et 50 dans realTick?

Répondre

6

Une façon est d'utiliser un garde -

|t when t < 50 -> ... 
7

En F #, une méthode recommandée pour match de motif sur les plages est d'utiliser active patterns. Si nous manipulons les noms de modèle, il regardera attentivement tout près de ce que nous voulons:

let (|``R0..50``|_|) i = 
    if i >= 0 && i <= 50 then Some() else None 

let realTick population = 
    match(getFullfitness population) with 
    | ``R0..50`` -> population 
    | _ -> childGeneration population 

correspondant sur gammes modèle est pris en charge dans OCaml, mais il est peu probable d'être ajouté à F #. Voir la demande de voix utilisateur correspondante au http://fslang.uservoice.com/forums/245727-f-language/suggestions/6027309-allow-pattern-matching-on-ranges.

6

Si vous devez choisir entre deux plages de numéros comme dans votre exemple, je simplement utiliser une expression if-then-else:

let realTick population = 
    let fitness = getFullFitness population 
    if 0 <= fitness && fitness <= 50 then 
    population 
    else 
    childGeneration population 

ou un garde simple:

let realTick population = 
    match getFullFitness population with 
    | fitness when 0 <= fitness && fitness <= 50 -> 
    population 
    | _ -> 
    childGeneration population 

Si votre choix réel est beaucoup plus compliqué, alors vous pouvez utiliser motifs actifs. Contrairement à @pad, j'utiliser un modèle actif paramétrées:

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

let realTick population = 
    match getFullFitness population with 
    | BetweenInclusive 0 50 -> 
    population 
    | _ -> 
    childGeneration population 

Un modèle actif d'ordre supérieur que j'ai trouvé parfois utile est un prédicat usage général:

let (|Is|_|) predicate x = 
    if predicate x then Some() else None 

En utilisant Is vous pourriez écrire quelque chose comme ceci:

let lessEq lo x = x <= lo 
let greaterEq hi x = hi <= x 

let realTick population = 
    match getFullFitness population with 
    | Is (greaterEq 0) & Is (lessEq 50) -> 
    population 
    | _ -> 
    childGeneration population 

Notez que, alors que quelque chose comme cela est exagéré dans un exemple simple comme celui-ci, il peut être pratique dans des scénarios plus compliqués. Personnellement, j'ai utilisé des modèles similaires pour implémenter une passe de simplification dans un compilateur qui optimisait ce modèle sur un grand nombre de cas d'opérations primitives et les propriétés des paramètres donnés à ces primitives.

Questions connexes