Type definitions

type Shape = Circle { r: Int } | Square { side: Int }
type Color = Red | Green | Blue

A type declares a tagged union. Each variant is a constructor.

Construction

c = Circle(3)          # positional, in field order
red = Red()            # a fieldless variant is still constructed

Both are struct values. Fields are read with .:

print(c.r)             # 3

Note that a bare Red without parentheses is the constructor function, not a value. Call it.

Matching

Variants match positionally by field order, which is where a type earns its keep:

area = match shape {
    Circle(r) => 3.14159 * r * r
    Square(side) => side * side
}

ecko check verifies exhaustiveness: a variant with no arm and no _ is an error before the program runs. Adding a variant to a type and forgetting a match somewhere is caught at analysis time rather than in production.

Fieldless variants match by name:

match colour {
    Red => "stop"
    Green => "go"
    Blue => "cold"
}

Built-in unions

Result (Ok/Err) and Option (Some/None) are predefined:

match parse(s) {
    Ok(v) => v
    Err(e) => default
}

They are ordinary data types for your own modelling, not the error channel. Nothing in the standard library returns them - failures throw. Reach for them when a value legitimately has two shapes, not to imitate error handling from another language.

Types and ai

A declared type is a schema, which is what makes typed model output ergonomic:

type Sentiment = Positive | Negative | Neutral

mood = ai[Sentiment] "classify this review: {text}"

match mood {
    Positive => reply_warmly()
    Negative => escalate()
    Neutral => file()
}

The model is constrained to the variants, the result is coerced to one, and the match over it is exhaustiveness-checked. A struct type works the same way, with each field coerced to its declared type:

type Person = { name: String, age: Int }
p = ai[Person] "extract the person from: {text}"

In mock mode an enum returns its first variant and a struct returns each field's mock, so the branch structure is exercised offline.

What type is not

Not a static type system. Field types annotate the declaration and drive ai schema generation and coercion; they are not checked on hand-written construction. Ecko stays dynamically typed - see Values & types - and the verification story is contracts.