Skip to main content

Extending types in F#

Just as you can extend existing types in C# with extension methods you can do the same in F# with type extensions. The difference is that extending types in F# helps you work in a functional matter with object orientation. Consider the following discriminated union that could be used for a card game.

type Suit = | Spades | Hearts | Diamonds | Clubs

type Card = | ValueCard of Suit * int | Knave of Suit | Queen of Suit | King of Suit | Ace of Suit

We would like to expose a hand as a type. In this type we can do all the object oriented behavior things like limiting number of cards in hand to 5, making sure that we don't have duplicate cards and so on. Great, but the problem is working with the type members we always need to reevaluate the type as we're changing member functions.

type Hand (cards : Card list) =
    member this.Cards = cards

So we keep the Hand type as simple as possible, and then we extend with functionality.

let isRoyalStraightFlush (cards : Card list) = 
    match cards with
    | Ace suit1 :: King suit2 :: Queen suit3 :: Knave suit4 :: ValueCard (suit5, 10) :: [] 
        when suit1 = suit2 && suit2 = suit3 && suit3 = suit4 && suit4 = suit_5
        -> true
    | _ -> false

The function isRoyalStraightFlush can be written and tested individually without any connection to the Hand object, and then we can extend the hand with this functionality like this.

type Hand with
    member x.IsRoyalStraightFlush = isRoyalStraightFlush x.Cards

I really like this way of working with object orientation in a functional manner.

comments powered by Disqus