F#模式匹配一​​系列数字

时间:2014-07-19 01:25:57

标签: f# pattern-matching

我有一个函数getFullFitness

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

我在函数realTick中模式匹配

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

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

3 个答案:

答案 0 :(得分:10)

一种方法是使用警卫 -

|t when t < 50 -> ...

答案 1 :(得分:9)

如果你在两个数字范围之间进行选择,就像你的例子一样,我愿意 只需使用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

请注意,虽然这样的事情在这样的简单示例中是过度的, 在更复杂的场景中它可以很方便。我个人使用了积极的 与此类似的模式在优化中实现简化传递 编译器,该模式匹配大量原始情况 给这些原语的参数的操作和属性。

答案 2 :(得分:8)

在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上的相关用户语音请求。