Tamas Koos
Tamas Koos

Reputation: 1063

Partial active pattern

I have to write a function for school which determines from a poker hand if it has two pairs. I should do it with partial active pattern, but I am stuck here.

let (|TwoPairs|_|) (x: (string * string) list) =
    x
    |> List.groupBy snd
    |> List.sortByDescending fst
    |> List.filter (fun (_, v) -> v |> List.length = 2)
    |> List.length = 2

let x2 =
    match [("S", "2"); ("S", "6"); ("S", "6"); ("S", "4"); ("S", "2")] with
    | TwoPairs p -> sprintf "Two pairs"
    | _ -> "Nothing"

How do I give back the last comparison as an option and what should be in Some _ in this case?

Upvotes: 2

Views: 260

Answers (1)

TheQuickBrownFox
TheQuickBrownFox

Reputation: 10624

I think the last line of your active pattern function is quite confusing because of the indentation and the implicit grouping due to operator precedence. I would write it like this to return an option:

let (|TwoPairs|_|) (x: (string * string) list) =
    x
    |> List.groupBy snd
    |> List.sortByDescending fst
    |> List.filter (fun (_, v) -> v |> List.length = 2)
    |> List.length
    |> function 2 -> Some () | _ -> None

When you return Option<unit>, then you don't have to bind to p, because it would be unit and represents the absence of a value. So you would use the pattern like this:

let x2 =
    match [("S", "2"); ("S", "6"); ("S", "6"); ("S", "4"); ("S", "2")] with
    | TwoPairs -> sprintf "Two pairs"
    | _ -> "Nothing"

I'm not sure if there's any benefit to using an active pattern here. It would be simpler to have a plain function that returns bool and use it like this:

if twoPairs [("S", "2"); ("S", "6"); ("S", "6"); ("S", "4"); ("S", "2")]
then sprintf "Two pairs"
else "Nothing"

Upvotes: 2

Related Questions