# algebraic data types for mortals

• Mathematics Student at Imperial
• PHP Core developer & documentation maintainer

# What are Algebraic Data Types?

## Definition

Warning: Software development, Computer Science, and Type Theory don't agree on what stuff means at time

## Definition

In computer programming, especially functional programming and type theory, an algebraic data type is a kind of composite type, i.e., a type formed by combining other types.

## Definition

In computer programming, especially functional programming and type theory, an algebraic data type is a kind of composite type, i.e., a type formed by combining other types.

Two common classes of algebraic types are product types (i.e., tuples and records) and sum types (i.e., tagged or disjoint unions, coproduct types or variant types).

# Product types

## Explanation for mortals

Product types allow you to have more than one value in a single structure, at the same time.

<?php

class BoolTuple2 {
public bool $boolean1; public bool$boolean2;

public function __construct(bool $boolean1, bool$boolean2) {
$this->boolean1 =$boolean1;
$this->boolean2 =$boolean2;
}
}


## Product type examples

<?php

class BoolTuple2 {
public function __construct(public bool $boolean1, public bool$boolean2) {}
}


## Product type examples

<?php

class BoolTuple2 {
public function __construct(public bool $boolean1, public bool$boolean2) {}
}


## Product type examples

### How many ways can we construct BoolTuple2?

<?php

class BoolTuple2 {
public function __construct(public bool $boolean1, public bool$boolean2) {}
}


## Product type examples

### How many ways can we construct BoolTuple2?

<?php

$trueTrue = new BoolTuple2(true, true);$trueFalse  = new BoolTuple2(true, false);
$falseTrue = new BoolTuple2(false, true);$falseFalse = new BoolTuple2(false, false);
<?php

class BoolTuple2 {
public function __construct(public bool $boolean1, public bool$boolean2) {}
}


## Product type examples

### How many ways can we construct BoolTuple2?

4 = 2 \times 2 = |bool| \times |bool|
<?php

class Digit {
public int $digit; public function __construct(int$digit) {
if ($digit < 0 ||$digit > 9) {
throw new ValueError('Value must be a digit');
}
$this->digit =$digit;
}
}

class Composite {
public function __construct(public BoolTuple2 $boolTuple2, public Digit$digit) {}
}


## Product type examples

<?php

class Digit {
public int $digit; public function __construct(int$digit) {
if ($digit < 0 ||$digit > 9) {
throw new ValueError('Value must be a digit');
}
$this->digit =$digit;
}
}

class Composite {
public function __construct(public BoolTuple2 $boolTuple2, public Digit$digit) {}
}


## Product type examples

### How many ways can we construct Composite?

<?php

class Digit {
public int $digit; public function __construct(int$digit) {
if ($digit < 0 ||$digit > 9) {
throw new ValueError('Value must be a digit');
}
$this->digit =$digit;
}
}

class Composite {
public function __construct(public BoolTuple2 $boolTuple2, public Digit$digit) {}
}


## Product type examples

### How many ways can we construct Composite?

|Composite| = |Digit| \times |BoolTuple2|
<?php

class Digit {
public int $digit; public function __construct(int$digit) {
if ($digit < 0 ||$digit > 9) {
throw new ValueError('Value must be a digit');
}
$this->digit =$digit;
}
}

class Composite {
public function __construct(public BoolTuple2 $boolTuple2, public Digit$digit) {}
}


## Product type examples

### How many ways can we construct Composite?

|Composite| = |Digit| \times |bool| \times |bool|
<?php

class Digit {
public int $digit; public function __construct(int$digit) {
if ($digit < 0 ||$digit > 9) {
throw new ValueError('Value must be a digit');
}
$this->digit =$digit;
}
}

class Composite {
public function __construct(public BoolTuple2 $boolTuple2, public Digit$digit) {}
}


## Product type examples

### How many ways can we construct Composite?

|Composite| = 10 \times 2 \times 2
<?php

class Digit {
public int $digit; public function __construct(int$digit) {
if ($digit < 0 ||$digit > 9) {
throw new ValueError('Value must be a digit');
}
$this->digit =$digit;
}
}

class Composite {
public function __construct(public BoolTuple2 $boolTuple2, public Digit$digit) {}
}


|Composite| = 40

# Sum types

## Explanation for mortals

Sum types are types where your value must be one of a fixed set of options.

## Sum type examples

### Booleans

bool = \{true, false\}

## Sum type examples

### Booleans

bool = \{true, false\}

### Our Digit class

Digit = \{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\}

## Sum type examples

### Lists

\textrm{List } a = [] \ | \ \textrm{Construct } a \ (\textrm{List } a)

## Sum type examples

### Lists

\textrm{List } a = [] \ | \ \textrm{Construct } a \ (\textrm{List } a)

### Strings

\textrm{String } c = \textsf{'}\textsf{'}\ | \ \textrm{Construct } c \ (\textrm{String } c)

## Union types

<?php

class BoolOrDigit {
public function __construct(public bool|Digit $boolOrDigit) {} } ## Sum type examples ## Union types <?php class BoolOrDigit { public function __construct(public bool|Digit$boolOrDigit) {}
}

## Union types

<?php

class BoolOrDigit {
public function __construct(public bool|Digit $boolOrDigit) {} } ### How many ways can we construct BoolOrDigit? BoolOrDigit = bool \cup Digit ## Sum type examples ## Union types <?php class BoolOrDigit { public function __construct(public bool|Digit$boolOrDigit) {}
}

### How many ways can we construct BoolOrDigit?

BoolOrDigit = bool \cup Digit
|BoolOrDigit| = |bool| + |Digit|

## Union types

<?php

class BoolOrDigit {
public function __construct(public bool|Digit $boolOrDigit) {} } ### How many ways can we construct BoolOrDigit? BoolOrDigit = bool \cup Digit |BoolOrDigit| = 2 + 10 = 12 # Pattern matching ## Reason why sum types are😎 ## Definition ## Definition In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. ## Definition In computer science, pattern matching is the act of checking a given sequence of tokens for the presence of the constituents of some pattern. The patterns generally have the form of either sequences or tree structures. ## Poor man Pattern matching example <?php class Nil {} class Leaf { public function __construct(public int$value) {}
}
class Node {
public function __construct(public Tree $left, public Tree$right) {}
}
class Tree {
public function __construct(public Nil|Leaf|Node $val) {} }  ## Poor man Pattern matching example <?php class Nil {} class Leaf { public function __construct(public int$value) {}
}
class Node {
public function __construct(public Tree $left, public Tree$right) {}
}
class Tree {
public function __construct(public Nil|Leaf|Node $val) {} } function depth(Tree$tree): int {
$val =$tree->val;
return match ($val::class) { Nil::class => 0, Leaf::class => 1, Node::class => 1 + max(depth($val->left), depth($val->right)), }; } ## Poor man Pattern matching example <?php$treeExample = new Tree(new Node(
new Tree(new Leaf(5)),
new Tree(new Node(
new Tree(new Node(
new Tree(new Nil()),
new Tree(new Leaf(2)),
)),
new Tree(new Leaf(6)),
))
));

print depth($treeExample); ## Poor man Pattern matching example <?php$treeExample = new Tree(new Node(
new Tree(new Leaf(5)),
new Tree(new Node(
new Tree(new Node(
new Tree(new Nil()),
new Tree(new Leaf(2)),
)),
new Tree(new Leaf(6)),
))
));

print depth($treeExample); 5 2 6 ## Poor man Pattern matching example <?php$treeExample = new Tree(new Node(
new Tree(new Leaf(5)),
new Tree(new Node(
new Tree(new Node(
new Tree(new Nil()),
new Tree(new Leaf(2)),
)),
new Tree(new Leaf(6)),
))
));

print depth($treeExample); 5 2 6 4 ### Output ## Poor man Pattern matching example <?php$treeExample = new Tree(new Node(
new Tree(new Leaf(5)),
new Tree(new Node(
new Tree(new Node(
new Tree(new Nil()),
new Tree(new Leaf(2)),
)),
new Tree(new Leaf(6)),
))
));

print depth(\$treeExample);

5

2

6

4

By girgias

• 714