Reputation: 515
I have a function getFullFitness
let getFullFitness population =
ResizeArray(population |> Seq.map snd) |> Seq.sum
and I pattern match in the function realTick
let realTick population =
match(getFullfitness population) with
|(50) -> population
| _ -> childGeneration population
Question is on the line |(50) -> population. Since getFullFitness returns an integer sum, how do i match values between 0 and 50 in realTick?
Upvotes: 5
Views: 6009
Reputation:
If you are choosing between two ranges of numbers like in your example, I would
just use a if-then-else
expression:
let realTick population =
let fitness = getFullFitness population
if 0 <= fitness && fitness <= 50 then
population
else
childGeneration population
or a simple guard:
let realTick population =
match getFullFitness population with
| fitness when 0 <= fitness && fitness <= 50 ->
population
| _ ->
childGeneration population
If your actual choice is much more complicated, then you might want to use active patterns. Unlike @pad, I would use a parameterized active pattern:
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
One higher-order active pattern I've found occasionally useful is a general purpose predicate:
let (|Is|_|) predicate x =
if predicate x then Some () else None
Using Is
you could write something like this:
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
Note that, while something like this is overkill in a simple example like this, it can be convenient in more complicated scenarios. I personally used active patterns similar to this to implement a simplification pass in an optimizing compiler that pattern matched over a large number of cases of primitive operations and properties of the parameters given to those primitives.
Upvotes: 10
Reputation: 41290
In F#, a recommended way to pattern match on ranges is to use active patterns. If we carefully manipulate pattern names, it will look quite close to what we want:
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
Pattern matching on ranges is supported in OCaml, but it's unlikely to be added to F#. See the related User Voice request at http://fslang.uservoice.com/forums/245727-f-language/suggestions/6027309-allow-pattern-matching-on-ranges.
Upvotes: 10