Algebraic data types

Enumerations in Swift are actually algebraic data types that are types created by combining other types. Algebraic data types are essential to many functional programming languages such as Haskell.

An algebraic data type is based on the idea of algebraic structures, which are a set of possible values and one or more operators to combine a finite number of these values into a single one. A well-known structure, for example, is (, +, -), a set of all integers with the plus and minus operations on them.

So an algebraic data type is a data type that is created by algebraic operations, specifically, with sum and product as our operations.

Additionally, algebraic data types are composite data types that may contain multiple values such as a data type with multiple fields, or they may consist of variants or multiple finite different values.

Simple types

The Boolean type is a simple algebraic data type as it may take one of two values: true or false. An instance of a Boolean type should be either true or false, but the instance cannot be both at once; it has to be one or the other unlike the struct/class properties and variables.

Composite types

Algebraic data types can also be composite types. For instance, a tuple of two Double values is a simple algebraic data type. Such a tuple could be expressed as having the (Double, Double) type, and an example value for this type could be (1.5, 3.2).

Composite type with variants

Algebraic data types can be composite types with variants as well. We could create an enum named Dimension to hold the length and width. We can express this enum in both us feet and metric meters. In Swift, we can define such an enum as follows:

enum Dimension {
    case us(Double, Double)
    case metric(Double, Double)
}

Then we can use the Dimension enumeration to create a variable as follows:

let sizeMetric = Dimension.metric(5.0, 4.0)

The algebra of data types

We have seen that enums in Swift are actually algebraic data types. Let's explore some examples to get more familiar with the topic.

The following example presents a simple enum NHLTeam with different options. The enum Team uses NHLTeam along with MLSTeam that we have defined before to combine Hockey and Soccer teams. Team can be either a Hockey NHL team or a Soccer MLS team:

enum NHLTeam {
    case canadiens
    case senators
    case rangers
    case penguins
    case blackHawks
    case capitals
}

enum MLSTeam {
    case montreal
    case toronto
    case newYork
    case columbus
    case losAngeles
    case seattle
}

struct HockeyAndSoccerTeams {
    var hockey: NHLTeam
    var soccer: MLSTeam
}

MLSTeam and NHLTeam each have six potential values. If we combine them, we will have two new types. Team can be either NHLTeam or MLSTeam, so it has 12 potential values that is the sum of NHLTeam and MLSTeam potential values. Therefore, the Team enum is a sum type.

To have a HockeyAndSoccerTeams structure, we need to choose one value for NHLTeam and one for MLSTeam so it has 36 potential values that are the product of NHLTeam and MLSTeam values. Therefore, HockeyAndSoccerTeams is a product type.

In Swift, an enumeration's option can have multiple values. If it happens to be the only option, then this enumeration becomes a product type. The following example presents an enum as a product type:

enum HockeyAndSoccerTeams {
    case Value(hockey: NHLTeam, soccer: MLSTeam)
}

Recursion types are another class of algebraic data types.

A recursive data type is a data type for values that may contain other values of the same type. An important application of recursion in computer science is in defining dynamic data structures such as arrays. Recursive data structures can dynamically grow to a theoretically infinite size in response to runtime requirements.

Operations used to do simple integer arithmetic can be modeled with enums. These operations let us combine simple arithmetic expressions. The Swift Programming Language(3.0) by Apple Inc. provides an example of simple integer arithmetic.

Another example of recursive data structures is a Tree that is implemented as a recursive data type:

enum Tree {
    case empty
    case leaf(Int)
    indirect case node(Tree, Tree)
}

let ourTree = Tree.node(Tree.leaf(1), Tree.node(Tree.leaf(2),
  Tree.leaf(3)))
print(ourTree)

Tree can be empty; it can have a leaf or another Tree as node.

As the data is nested, the enumeration used to store the data also needs to support nesting, which means that the enumeration needs to be recursive.

The compiler has to insert a layer of indirection when it works with recursive enumerations. We indicate that an enumeration case is recursive by writing indirect before it.

The following example presents the search function on Tree:

func searchInTree(_ search: Int, tree: Tree) -> Bool {
    switch tree {
    case .leaf(let x):
        return x == search
    case .node(let l as Tree, let r as Tree):
        return searchInTree(search, tree:l) || searchInTree(search, tree:r)
    default:
        return false
    }
}

let isFound = searchInTree(3, tree: ourTree) // will return true
print(isFound)

As we can create sum, product, or recursion types in Swift, we can say that Swift has first-class support for algebraic data types.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset