Contracts and fit
spec declares a capability boundary, type provides an implementation, and fit establishes conformance or adds methods without modifying the original type definition.
Object Contracts
spec Named {
let name: string;
func display(): string;
}
type User: Named {
let name: string;
func display(): string {
return self.name;
}
}
func print_name(value: Named) {
println(value.display());
}
A field must match in name, type, and let/var form. A method must match in name, parameters, and return type. A relationship in the declaration header states that the type author explicitly promises conformance to the contract.
Callable Contracts
spec Mapper(value: int): int;
let double: Mapper = (value: int) -> value * 2;
println("{0}", double(21));
The callable form describes only a function signature and is suitable for lambdas, top-level functions, and method values. It cannot appear in type Foo: Mapper or fit Foo: Mapper.
Union Contracts
spec Identifier: int | string;
let id: Identifier = "user-42";
let label = match id {
number: int { "numeric" }
text: string { text }
};
The union form means “one of these members.” A value must first be narrowed with match before it can be used as a concrete member.
Intersection Contracts
spec Readable {
func read(): string;
}
spec Writable {
func write(value: string): void;
}
spec ReadWrite: Readable & Writable;
The intersection form combines multiple object contracts and can be used in type positions or generic constraints. A concrete type should declare conformance to each constituent object contract rather than directly declaring conformance to the intersection contract.
Satisfy a Contract with fit
spec DisplayName {
func display_name(): string;
}
type Account {
let name: string;
}
fit Account: DisplayName {
func display_name(): string {
return self.name;
}
}
fit is useful when the original type cannot be modified or when an adaptation should live in a separate module.
Add Extension Methods with fit
When no target spec is listed, fit can add methods only:
fit Account {
func greeting(): string {
return "Hello, " + self.name;
}
}
Whether an extension can be used across modules is determined by the visibility of both the module and the fit. To export it, use open fit in a public module. The relationship and extension methods take effect in the current file only after that module is imported.
Recommendations
- Put contracts intrinsic to a type in the
typedeclaration header. - Use
fitfor third-party adaptations or capabilities enabled by importing a module. - Do not treat
specas implementation inheritance; it describes only a visible contract. - Do not rely on implicit structural matching; conformance must be declared explicitly.