Algebraic Data Types

As mentioned earlier, Rust's type system is algebraic. We can create new types from combinations of existing types. We can make both products (product types) and coproducts (sum types). Rust's products are tuples or structures (keyword struct) and its coproducts are enumerations (keyword enum).

Structures

Structures group things together; we have both this and that.

For example, here is a structure from epochs-cli


#![allow(unused_variables)]
fn main() {
struct Datelike {
    source: String,
    viewed_as: View,
    epochs: HashMap<String, NaiveDateTime>,
}
}

Each instance of a Datelike struct contains all of those three things.

Enumerations

Enumerations offer a choice; we have either this or that.

For example, here is an enum from epochs-cli


#![allow(unused_variables)]
fn main() {
enum View {
    Decimal,
    Float,
    Hexadecimal,
    UUIDv1,
}
}

Each instance of a View enum contains exactly one of those four things.

Tuples

We've already talked about tuples a bit, but they belong here too as they are products. Perhaps the simplest product type is a pair of other types like (char, i32). It's kind of like a struct without the labels. We refer to the elements by number. If t is a pair, then t.0 is the first thing and t.1 is the second.

Unit

The empty tuple, (), is Rust's unit type. In Rust, everything is an expression; there are no statements. That is, everything returns a value. The unit type is the type returned when things "don't return anything."

Conclusion

Most type systems have things like tuples and structures, but many lack rich enumerations like Rust has. You may have used Perl's Types::Standard::Enum, which provides C-style enumerations. Rust's enumerations can also contain data, so they're a more proper coproduct.

A type system like Rust's can be used to make illegal states unrepresentable.