Types
Gale builds richer types from fixed-length tuples, transparent aliases,
literal unions, and recursive algebraic data types. Generic parameters use
angle brackets, and exhaustive match handles every finite shape.
module types
pub type Pair<A, B> = (A, B)
pub fn make_pair(left: Integer, right: Binary) -> Pair<Integer, Binary> { (left, right)}An atom literal such as :ok is also a type containing one value. Joining
literal types with | creates a finite union that match can cover
exhaustively. Boolean is the built-in union :true | :false.
module types
pub fn label(status: :ok | :error) -> Binary { match status { :ok -> "ok" :error -> "error" }}Guard type tests refine broader values inside their arm. Gale emits the native Elixir guard; it does not synthesize guards merely because a function parameter already has a precise type.
module types
pub fn as_binary(value: Term) -> Option<Binary> { match value { binary when is_binary(binary) -> Some(binary) _ -> None }}An algebraic data type names its constructors and their payloads. ADTs can be
recursive: Tree<A> contains either Leaf or a node holding a value and two
more trees. Nullary constructors emit snake-case atoms; constructors with
payloads emit tagged tuples.
module types
pub type Tree<A> = | Leaf | Node(A, Tree<A>, Tree<A>)
pub fn sum(tree: Tree<Integer>) -> Integer { match tree { Leaf -> 0 Node(n, left, right) -> n + sum(left) + sum(right) }}