Reporting the highest satisfied poker hand in F# I'm learning F# by doing various small projects. One of them is a problem where the program reads Poker hands and rates them. It's Texas Hold'Em, so for each player it tries every five card selection from seven cards.

When it's time for scoring I have made a set of functions that each evaluate a hand and produces an Score option of whether that hand matches or not:

type Score =
{ Points: int
  Desc: string }

val tryStraightFlush: PokerHand -&gt; Score option
val tryFourOfAKind: PokerHand -&gt; Score option
// more functions ..      
val getHighCard: PokerHand -&gt; Score option

type PokerHand =
  class
    new : cards:Card list -&gt; PokerHand
    member Cards : Card list
    member HighCard : Card option
  end


But now I have a problem, because I need to use the options that these functions produce, so I cannot do a match like this:

//Non-working code. 
//Something roughly similar to this would be nice.
//But I need to use the values from the "try"-functions
//and they get thrown away here:

let scoreCards (hand: PokerHand) =
match hand with
| r when (tryStraightFlush hand) &lt;&gt; None -&gt; //prod. Score 
| r when (tryFourOfAKind hand) &lt;&gt; None -&gt; //prod. Score 
// more code


Instead my code ends up looking like this, and I have to say I don't like this deep nesting.. How can I have a small function for testing each type of configuration, while avoiding a deeply nested if-expressions? 

let scoreCards (hand: PokerHand) =
  // Too much nesting!
  let r = tryStraightFlush hand
  if r &lt;&gt; None then
    r.Value 
  else
    let r = tryFourOfAKind hand
    if r &lt;&gt; None then
        r.Value
    else
        let r = tryFullHouse hand
        if r &lt;&gt; None then
            r.Value
        else
            let r = tryFlush hand
            if r &lt;&gt; None then
                r.Value
            else
                // nesting continues..
The solution here is to use an active pattern, which enables you to create a custom matching function.

You can even reuse your existing functions.

It would look like

let |StraightFlush|_| hand = tryStraightFlush hand


then you can use it like this

match hand with
|Straightflush(score) -&gt; ...
| ....