Reputation: 1063
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
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