Renderingla

Data types

Faber has a static, type-first type system. Every declaration places the type before the name: textus nomen, not nomen: textus. The type system covers scalar primitives, generic collections, sized numerics, tensors, and GPU-facing register types.

Primitive types

TypeRoleExample literal
textusUnicode string"Salve, munde"
asciiFixed machine token'solum:lege'
numerusSigned integer (default i64)42
fractusFloating-point (default f64)3.14
bivalensBooleanverum, falsum
vacuumUnit / no value
nihilNull / absentnihil
instansDuration / time instant
jsonCompile-time JSON value{ "key": "value" }
octetiHex byte sequence\|00ff\|

Sized numeric types

numerus and fractus have default widths (i64 and f64) and explicit width forms:

fixum numerus<i32> narrow ← 7 ∷ numerus<i32>
fixum numerus<u64> wide ← 255 ∷ numerus<u64>
fixum fractus<f32> single ← 1.5 ∷ fractus<f32>

Width sugar is available in type position: i8u64, f16, f32, f64 are equivalent to numerus<W> / fractus<W>.

Nullable types

Nullable values use the union syntax T ∪ nihil:

functio find(textus key) → numerus ∪ nihil {
    redde nihil
}

functio maybe() → textus ∪ nihil {
    redde nihil
}

There is no T? or Option<T> syntax in Faber. The union is explicit.

Type aliases

typus UserId = numerus

Generics

Functions, type aliases, genus, and implendum accept type parameters with <T> syntax:

functio identitas<T>(T valor) → T {
    redde valor
}

functio primum<T>(lista<T> res) → T ∪ nihil {
    redde res.primus()
}

Explicit call-site type arguments are supported:

functio identitas<T>(T valor) → T { redde valor }

fixum numerus value ← identitas<numerus>(7)

Collections

TypeRoleSugar
lista<T>Ordered dynamic collectionlf32, lu32
tabula<K, V>Key-value map
tensor<T, Figura>Dense fixed-shape buffertf32[4], ti64[2,3]
sparsa<T, Figura>Sparse fixed-shape buffersf32[4], si64[2,3]
intervallumRange type
copia<T>Unordered set
cursor<T>Lazy stream
fixum lista<numerus> nums ← [1, 2, 3]
fixum tabula<textus, numerus> scores ← { "alice": 10, "bob": 20 }

Tensor types

tensor<T, Figura> is the dense fixed-shape container:

FormMeaning
tensor<T, Figura>Canonical spelling
tensor<T, []>Rank-0 (scalar container)
tensor<T, _>Shape inference hole
tensor<T, [N]>Rank-1 vector
tensor<T, [N, M]>Rank-2 matrix
fixum tensor<fractus<f32>, []> scalar ← vacua
fixum tensor<numerus, [4]> vector ← [1, 2, 3, 4] ↦ tensor<numerus, [4]>
fixum numerus ∪ nihil first ← vector[0]

GPU core types

These are recognised by the systems lane for GPU and register work. Package targets that lack hardware support reject them:

functio half(f16 x) → f16 { redde x }

functio add(matrix<f32, [2, 2]> a, matrix<f32, [2, 2]> b) → matrix<f32, [2, 2]> {
    redde a.addita(b)
}

functio swap(atomic<i32> cell, i32 value) → i32 {
    redde cell.exchange(value)
}

Borrow markers on types

Borrow markers (de, in, ex) can appear on types in parameter positions to indicate how a value is passed:

# shared borrow — caller retains ownership
functio imprime(de textus label) → vacuum { }

# mutable borrow — caller lends mutable access
functio duplica(in numerus value) → vacuum { }

# move — caller gives up ownership
functio consume(ex textus buffer) → textus {
    redde buffer
}

Comparison policy

OperatorFamilyBehaviour
, Exact equalityIdentical types required; nihil bypass
, Numeric value equalityNumeric lattice only
<, , >, OrderingNumeric, instant, scalar text
intraRange containmentNumeric in range
interCollection membershipElement in collection