Data Types for Desiderius – [part 2]

Blog1 Comment on Data Types for Desiderius – [part 2]

Data Types for Desiderius – [part 2]

In case you missed it, I picked up my old hobby of playing bridge, but because I do not have any friends to play with, I am making a Bridge Bot. My ultimate goal is to participate in the World Championships of Computer Bridge.

The basic data types

I started by creating a few abstract data types to represent the game, and already I ran into quite some interesting trade offs. I was planning to do a write up once I have finished the bidding part of the tool, but I think there is enough to talk about right now.

Players

Players are always indicated by directions of the wind, so that is quite easy

type Player = West | South | North | East

Cards

Cards have a value, called rank, ranging from Ace to 2:

type Rank = A | K | Q | J | T | Nine | Eight | Seven | Six | Five | Four | Three | Two

and a suit, one of these four:

type Suit = Spades | Hearts | Diamonds | Clubs

Together this defines cards

type Card = Card of Suit * Rank

Now, a hand of cards is just a list of cards

type Hand = Hand of list<Card>

and a whole game is four of them:

type Deal = list<Hand>

These are already some cases where dependent types would have been nice, as we could have express that hands are always a list of 13 cards and a deal is a list of 4 of those, but yeah 🙂

There is one more thing we need to model: we need to know in the list of the 4 hands, whose hand is whose, since the dealer changes after every round and this has impact on the game, more on that later.

This is I think the first decision to make. We could make the deal into tuples of (Player, Hand) but that is a bit redundant as there is a clear order in the players, being the order of the wind directions. So, it is enough to just store the name of the dealer, which is the player that goes first, even though in professional games the dealer does not actually deal. In the portable bridge notation (more on that in a subsequent episode) also only the dealer is saved.

In the end I decided to make a type for the dealer as a means of documentation, to make it clear for users of the code what the role of this player is. In theory, it could also means something else, like who was the leader of the bid, so it became:

type Dealer = Dealer of Player

and

type Deal = Deal of Dealer * list<Hand>

I really like to add discriminators as names to things (even if there is just one option as here with Dealer) or earlier with Hand. It serves as nice documentation, not just when reading the type (which is something you would not do too often) but also when reading and writing functions.
Especially when you do pattern matching, I believe it pays of:

let pointsinHand(h:Hand): int = 
match h with
   | Hand [] -> 0
   | Hand list -> <something to compute the value of a hand with cards

When you read this in your mind, you read the first line as “an empty hand is worth zero points” instead of “an empty list is”

Another argument for the discriminator, it is easier to add new cases later, as you will then only have to add a new pattern to match against, instead of then wrapping them into discriminators, so if you do not know where you are going, this is useful.

One thought on “Data Types for Desiderius – [part 2]

Comments are closed.

Back To Top