# 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 -> Score option
val tryFourOfAKind: PokerHand -> Score option
// more functions ..
val getHighCard: PokerHand -> Score option

type PokerHand =
class
new : cards:Card list -> 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) <> None -> //prod. Score
| r when (tryFourOfAKind hand) <> None -> //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 <> None then
r.Value
else
let r = tryFourOfAKind hand
if r <> None then
r.Value
else
let r = tryFullHouse hand
if r <> None then
r.Value
else
let r = tryFlush hand
if r <> None then
r.Value
else
// nesting continues..

• You want to look at active patterns Oct 4 '16 at 7:30
• @JohnPalmer Why you do not want to write the answer?
– user110704
Oct 4 '16 at 9:04
• Check this out stackoverflow.com/questions/39262053/… Oct 5 '16 at 1:12

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) -> ...
| ....

• Thank you very much @john-palmer. I didn't learn about active patterns until now, but I see that they are indeed the way to do this. Oct 4 '16 at 9:40