Composite types
Goal: declare your types with
decl(one keyword for struct, enum, and interface), match sum types with pattern matching, and get to know the variant-set.
decl: one keyword, three forms
Section titled “decl: one keyword, three forms”decl declares struct, enum, and interface; the body says which one:
decl Point { x: int; y: int } // fields 'name: type' → struct (product)decl Shape { Circle(int); Square } // variants 'Name(...)' → enum (sum)decl Drawable { fn draw() -> []byte } // signatures 'fn ...' → interfaceThe three share the act of declaring a contract, and the body disambiguates. Members are separated
by ; or Newline, never a comma (comma is for groups in (), like arguments and tuples).
Methods are external functions with a receiver (Go style); the struct only holds data:
decl Dog { nome: string }fn (d: *Dog) speak() -> string { return "{{d.nome}}: woof" } // receiver '*Dog'
d := Dog{ nome: "Rex" } // literal: fields by ',' (a group of values)io.println(d.speak()) // UFCS: d.speak() ≡ speak(d)Constructors are associated functions (receiver = just the type, no name):
fn (Dog) named(n: string) -> Dog { return Dog{ nome: n } }rex := Dog.named("Rex") // call by dotSum types and pattern matching
Section titled “Sum types and pattern matching”An enum with a payload is a sum type; match breaks it down by variant, binding the fields by position:
decl Event { Tick; Click(int, int); Quit }
fn describe(e: Event) -> string { return match e { Tick => "tick" Click(x, y) => "click at ({{x}}, {{y}})" Quit => "quit" } // closed domain: all variants, '_' would be an error}An enum without a payload is a simple enumeration or a state machine:
decl State { Idle; Running; Done }
fn step(s: State) -> State { return match s { Idle => Running Running => Done Done => Done }}Composition via @embeds (there is no inheritance)
Section titled “Composition via @embeds (there is no inheritance)”Reuse is composition, with declared promotion:
decl Animal {}fn (a: *Animal) speak() -> string { return "..." }
@embeds(Animal, methods)decl Cat { animal: Animal; nome: string }
c := Cat{ animal: Animal{}, nome: "Mia" }c.speak() // promoted: calls Animal.speak directlyVariant-set: a subset of a sum
Section titled “Variant-set: a subset of a sum”Shape{Circle} is “a Shape, guaranteed Circle”: a set of variants. In type position,
Name{...} is a variant-set; in value position, Name{...} is a struct literal (the position separates them):
fn so_clicks(e: Event{Click}) { ... } // accepts only the Click variant (checked in the type)It is the same mechanism as the error-sets of the next chapter: a closed domain that sub-sets itself, with
{...} closing the subset.
alias gives a transparent second name to a type that already exists (different from decl, which creates
a new type):
alias UUID = u128 // UUID IS u128, interchangeableNext: 04 · Errors