In this post, I want to talk about types in F#. Types are used to model a certain data that a programmer wants in the software. There are primitive types available for F#, such as string and int. To model data we would compose these primitive types, and then it would also be possible to compose a new type from the type we created. In OO paradigm, it is common to define a type with its data and behaviour. In functional programming data is modelled using types without defining what it does, but more on what it is.
The Record type
This type is capable of holding a record of values. For example, lets say we need a data of a Person for the software we are building. The Person is made up following data having
and an Age
and an Address
and an SSN(social security number)
and a PhoneNumber
and an EmailId
and a BloodGroup
The record type, also known as the “AND” type, like you see above, holds a combination of values that makes that type. Lets define this type in F# using the type keyword.
That’s the Person type in F#. Its pretty readable even for a non-coder member in the team. The Person type is composed of all primitive types. But, types can hold a custom type too.
But, why would this type need to hold another type? Well, that’s a question that could be up for a discussion within your team and see what your program would be doing with the values in the type. Our Person type holds the address as a string. We know that address is made up of
and a PostCode
and a City
and a Country
The address is an “AND” type and we can create a record type in F#. We already created one record type called Person, lets create another one for Address
Now our Address is very well typed. We know what address is composed of and so does our software.
Can we define a better type for the BloodGroup ? Lets say we are defining blood groups with the ABO system https://www.nhs.uk/conditions/blood-groups/ . BloodGroup can be one of these :
This is not an “AND” type. This an “OR” type. That is the blood group can only be one of those values. Its also called a choice type. If you are talking to a fellow functional programmer, you call this a Discriminated Union.
That is how you define an “OR” type which can have values A or B or O or AB. A choice type has a pipe in its definition. Notice that both “AND” and “OR” types are defined using the type keyword, but they still differ in the definition. For an OO programmer this may look like the enum types. But in F#, these are much more powerful. I will leaves those details for another post. For now, lets keep this simple.
In the initial version of Person type, we had all the primitive types. Now Address and BloodType are a type of their own and the Person type composes them. Note that there are other values like Name, Age, SSN etc. that are still primitive type. One would argue that they should be thier own type too. But, that can also be discussion with your team with your domain experts. The power of F# is not just leveraging functional programming, but also efficient domain modelling. In F#, you can create simple types like below. So now, Age is not just any int, its a type of Age.
type Age = Age of int
I think our data is very well modelled. But, I am not so sure that every person may have an emailId. Ok, so are you saying emailId can be null? Well, that’s in an OO world. There are patterns to keep the null values contained or avoidable in OO using Null object pattern or other ways. If we had one Euro for every NullReferenceException, then we would have solved poverty in this world. We did not solve poverty with F# yet, but nulls are something F# developers need not have to worry or deal with. F# compiler will let you know if a certain value that needs to have value is not set correctly.
Alright, how do we tell the F# compiler that EmailId is optional? Below you can see the final version of the Person type.
Note the “option” on the EmailId. That’s it, the compiler knows that it is an optional value. You can set “Some” value to this or “None”.
This is how we create a Person.
Hope you enjoyed this post.
Until next time. Cheers.