## 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.
• `Coerce` - to convert simple data types to their underlying representation.

### 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.

### Derivation of Coerce

We can automatically derive implementations of the `Coerce` type class. The `Coerce` class converts a simple (one-case) data type to its underlying implementation.

``````enum Shape with Coerce {
case Circle(Int32)
}

def main(): Unit \ IO =
let c = Circle(123);
``````

We cannot derive `Coerce` for an enum with more than one case. For example, if we try:

``````enum Shape with Coerce {
case Circle(Int32)
case Square(Int32)
}
``````

The Flix compiler emits a compiler error:

``````❌ -- Derivation Error --------------------------------------------------

>> Cannot derive 'Coerce' for the non-singleton enum 'Shape'.

1 | enum Shape with Coerce {
^^^^^^
illegal derivation

'Coerce' can only be derived for enums with exactly one case.
``````