2014-07-19 68 views
0

我有一个函数getFullFitness在功能realTickF#图案匹配的数字范围

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

问题是上线

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

和我模式匹配|(50) - >人口。由于getFullFitness返回一个整数和,我如何在realTick中匹配0到50之间的值?

回答

6

的一种方法是使用保护 -

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

在F#中,推荐的方式,模式匹配的范围是使用active patterns。如果我们仔细操作模式的名字,它的外观非常接近我们想要的东西:

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 

模式上范围匹配OCaml的支持,但它不太可能被添加到F#。请参阅http://fslang.uservoice.com/forums/245727-f-language/suggestions/6027309-allow-pattern-matching-on-ranges上的相关用户语音请求。

6

如果你两个数字范围之间就像在你的榜样选择,我会 只用一个if-then-else表达:

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

或简单后卫:

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

如果你的实际选择要复杂得多,那么你可能需要使用 活动模式。不像@pad,我会用一个参数活跃模式:

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 

一个我发现有时候是有用的高阶主动模式是一般 目的谓:

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

使用Is你可以写是这样的:

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 

需要注意的是,虽然这样的事情是矫枉过正在这样一个简单的例子, 它可以在更复杂的情况下方便。我个人使用与此类似的活动 模式在优化 编译器中实现简化通过,该编译器在大量基本操作的例子和为这些基元提供的参数的属性上进行模式匹配。