Out-of-the-box behavior for types

Immutability and built-in equality with no coding

One nice thing about F# is that most types immediately have some useful "out-of-the-box" behavior such as immutability and built-in equality, functionality that often has to be explicitly coded for in C#.

By "most" F# types, I mean the core "structural" types such as tuples, records, unions, options, lists, etc. Classes and some other types have been added to help with .NET integration, but lose some of the power of the structural types.

This built-in functionality for these core types includes:

  • Immutability

  • Pretty printing when debugging

  • Equality

  • Comparisons

Each of these is addressed below.

F# types have built-in immutability

In C# and Java, it is has become good practice to create immutable classes whenever possible. In F#, you get this for free.

Here is an immutable type in F#:

type PersonalName = {FirstName:string; LastName:string}

And here is how the same type is typically coded in C#:

class ImmutablePersonalName
{
    public ImmutablePersonalName(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }

    public string FirstName { get; private set; }
    public string LastName { get; private set; }
}

That's 10 lines to do the same thing as 1 line of F#.

Most F# types have built-in pretty printing

In F#, you don't have to override ToString() for most types -- you get pretty printing for free!

You have probably already seen this when running the earlier examples. Here is another simple example:

The output is:

Most F# types have built-in structural equality

In C#, you often have to implement the IEquatable interface so that you can test for equality between objects. This is needed when using objects for Dictionary keys, for example.

In F#, you get this for free with most F# types. For example, using the PersonalName type from above, we can compare two names straight away.

Most F# types are automatically comparable

In C#, you often have to implement the IComparable interface so that you can sort objects.

Again, in F#, you get this for free with most F# types. For example, here is a simple definition of a deck of cards.

We can write a function to test the comparison logic:

And let's see how it works:

Note that the Ace of Hearts is automatically greater than the Two of Hearts, because the "Ace" rank value comes after the "Two" rank value.

But also note that the Two of Hearts is automatically greater than the Ace of Spades, because the Suit part is compared first, and the "Heart" suit value comes after the "Spade" value.

Here's an example of a hand of cards:

And as a side benefit, you get min and max for free too!

Last updated

Was this helpful?