(* Lecture 4: Poker *) (* Author: Carsten Schuermann *) datatype Suit = Club | Spade | Heart | Diamond datatype Rank = Ace | King | Queen | Jack | Ten | Nine | Eight | Seven | Six | Five | Four | Three | Two datatype Card = Card of Rank * Suit datatype Hand = Empty | Fan of Hand * Card (* dominate (C1, C2) = B Invariant: B holds iff C1 dominates C2 (note the syntax as anonymous function) *) val dominate : Suit * Suit -> bool = fn (Diamond, _) => false | (Heart, Diamond) => true | (Heart, _) => false | (Spade, Diamond) => true | (Spade, Heart) => true | (Spade, _) => false | (Club, Diamond) => true | (Club, Heart) => true | (Club, Spade) => true | (Club, _ ) => false (* equalSuit (C1, C2) = B Invariant: B holds iff C1 == C2 *) fun equalSuit (Club, Club) = true | equalSuit (Spade, Spade) = true | equalSuit (Heart, Heart) = true | equalSuit (Diamond, Diamond) = true | equalSuit _ = false (* equalRank (R1, R2) = B Invariant: B holds iff R1 == R2 *) fun equalRank (Ace, Ace) = true | equalRank (King, King) = true | equalRank (Queen, Queen) = true | equalRank (Jack, Jack) = true | equalRank (Ten, Ten) = true | equalRank (Nine, Nine) = true | equalRank (Eight, Eight) = true | equalRank (Seven, Seven) = true | equalRank (Six, Six) = true | equalRank (Five, Five) = true | equalRank (Four, Four) = true | equalRank (Three, Three) = true | equalRank (Two, Two) = true | equalRank (_, _) = false (* suit S H = H' Invariant: If S is a suit and H is a hand then H' < H is a hand that only contains cards of suit S *) fun suit S Empty = Empty | suit S (Fan (H, C as Card (_, S'))) = if (equalSuit (S, S')) then Fan (suit S H, C) else suit S H (* cards_of_a_kind N R H = B Invariant: B holds iff H contains N cards of rank R *) fun cards_of_a_kind 0 _ _ = true | cards_of_a_kind n R Empty = false | cards_of_a_kind n R (Fan (H, Card (R', _))) = if equalRank (R, R') then cards_of_a_kind (n-1) R H else cards_of_a_kind n R H (* cards_of_a_suit N S H = B Invariant: B holds iff H contains N cards of suit S *) fun cards_of_a_suit 0 _ _ = true | cards_of_a_suit n S Empty = false | cards_of_a_suit n S (Fan (H, Card (_, S'))) = if equalSuit (S, S') then cards_of_a_suit (n-1) S H else cards_of_a_suit n S H (* has P = B Invariant: If P is a predicate (P : Rank -> bool) B holds iff P holds for at least one ranks R (P R) *) fun has P = P Ace orelse P King orelse P Queen orelse P Jack orelse P Ten orelse P Nine orelse P Eight orelse P Seven orelse P Six orelse P Five orelse P Four orelse P Three orelse P Two (* Three predicates *) fun pair H = fn R => cards_of_a_kind 2 R H fun three_of_a_kind H = fn R => cards_of_a_kind 3 R H fun four_of_a_kind H = fn R => cards_of_a_kind 4 R H (* Example hand 1 *) val hand1 : Hand = Fan (Fan (Fan (Fan (Fan (Empty, Card (King, Heart)), Card (Ace, Diamond)), Card (Seven, Spade)), Card (King, Club)), Card (King, Diamond)) (* Example hand 2 *) val hand2 : Hand = Fan (Fan (Fan (Fan (Fan (Empty, Card (Ace, Diamond)), Card (Queen, Diamond)), Card (Six, Heart)), Card (King, Club)), Card (King, Diamond))