Since F# is a multi-paradigm language, it has a mixture of types: some from its functional background, and some from its object-oriented background.
Generally, the types in F# can be grouped into the following categories:

  • Common .NET types. These are types that are part of .NET CLI, and which are easily portable to every .NET language. This include types like: primitive types ( bool, int, float etc.), enums, structs and classes
  • F# specific types. These are types that are part of the F# language and are designed for pure functional programming.

Difference between .Net tyes and F# specific types is noticeable and comes from fact that .Net was designed mostly as object-oriented environment and thinking about types differs between object-oriented and functional programming. In the first one program will have a strong focus on behaviour rather than data, so it will use a lot of polymorphism and inheritance to provide object with wanted behaviour. On the other hands, functional program will have a strong focus on data types rather than behaviour. F# puts much more emphasis on designing types correctly what is very useful in Domain Design Development. What is more types in functional programming presents only data without any behaviour.

Also F# types have some huge advantages over standard .Net types, such as:

  • They are immutable
  • They cannot be null
  • They have built-in structural equality and comparison
  • They have built-in pretty printing

Algebraic data type

In functional programming and type theory, an algebraic data type is a kind of composite type - a type formed by combining other types. Two common classes of algebraic type are product types and sum types.

type A = B "+" C //Sum type
type Z = A "*" D //Product type

The key point is that an infinite number of new types can be made by combining existing types together using these "+" and "*" methods in various ways and they can be used to model anything including lists, trees, and other recursive types

Another important factor is fact that values of algebraic types are analysed with pattern matching, which identifies a value by its constructor or field names and extracts the data it contains.

Fast types overview

  • Tupple - grouping of unnamed but ordered values, possibly of different types.

    let s = ( "one", 1, 2.0 )

  • Record - simple aggregate of named values

    type Customer = { First : string; Last: string; SSN: uint32; AccountNumber : uint32; }

  • Discriminated Union - provide support for values that can be one of a number of named cases, possibly each with different values and types. Discriminated unions are useful for heterogeneous data; data that can have special cases, including valid and error cases; data that varies in type from one instance to another; and as an alternative for small object hierarchies. In addition, recursive discriminated unions are used to represent tree data structures.

    type Shape =
        | Rectangle of width : float * length : float
        | Circle of radius : float
        | Prism of width : float * float * height : float
    
    
    let rect = Rectangle(length = 1.3, width = 10.0)
    
  • Enums - integral types where labels are assigned to a subset of the values. You can use them in place of literals to make code more readable and maintainable.

    type Color =
       | Red = 0
       | Green = 1
       | Blue = 2
    
    
    let col1 : Color = Color.Red