## Automatic Derivation

Flix supports automatic derivation of several traits, including:

• Eq — to derive structural equality on the values of a type.
• Order — to derive a total ordering on the values of a type.
• ToString — to derive a human-readable string representation on the values of a type.
• Sendable — to enable the values of an (immutable) type to be sent over a channel.

### Derivation of Eq and Order

We can automatically derive instances of the Eq and Order traits using the with clause in the enum declaration. For example:

enum Shape with Eq, Order {
case Circle(Int32)
case Square(Int32)
case Rectangle(Int32, Int32)
}

The derived implementations are structural and rely on the order of the case declarations:

def main(): Unit \ IO =
println(Circle(123) == Circle(123)); // prints `true`.
println(Circle(123) != Square(123)); // prints `true`.
println(Circle(123) <= Circle(123)); // prints `true`.
println(Circle(456) <= Square(123))  // prints `true`.

Note: Automatic derivation of Eq and Order requires that the inner types of the enum implement Eq and Order themselves.

### Derivation of ToString

We can also automatically derive ToString instances:

enum Shape with ToString {
case Circle(Int32)
case Square(Int32)
case Rectangle(Int32, Int32)
}

Then we can take advantage of string interpolation and write:

def main(): Unit \ IO =
let c = Circle(123);
let s = Square(123);
let r = Rectangle(123, 456);
println("A \${c}, \${s}, and \${r} walk into a bar.")

which prints:

A Circle(123), Square(123), and Rectangle(123, 456) walk into a bar.

### Derivation of Sendable

We can automatically derive implementations of the Sendable trait (which allow values of a specific type to be sent over a channel). For example:

enum Shape with Sendable, ToString {
case Circle(Int32)
}

def main(): Unit \ IO =
region rc {
let (tx, rx) = Channel.buffered(rc, 10);
Channel.send(Circle(123), tx); // OK, since Shape is Sendable.
println(Channel.recv(rx))
}

We cannot derive Sendable for types that rely on scoped mutable memory. For example, if we try:

enum Shape[r: Region] with Sendable {
case Circle(Array[Int32, r])
}

The Flix compiler emits a compiler error:

❌ -- Safety Error --------------------------------------

>> Cannot derive 'Sendable' for type Shape[b27587945]

Because it takes a type parameter of kind 'Region'.

1 | enum Shape[r: Region] with Sendable {
^^^^^^^^
unable to derive Sendable.

This is because mutable data is not safe to share between threads.