2014-07-19 75 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 

需要注意的是,雖然這樣的事情是矯枉過正在這樣一個簡單的例子, 它可以在更復雜的情況下方便。我個人使用與此類似的活動 模式在優化 編譯器中實現簡化通過,該編譯器在大量基本操作的例子和爲這些基元提供的參數的屬性上進行模式匹配。