--- Title: 8 Type System Prev: Data Structures Next: Trait System --- ## 8. Type System ### 8.1 Types vs Traits The language distinguishes between types (what things are) and traits (how things behave): **Types** define the concrete structure and memory layout: - `Point` - A struct type with two fields - `Rectangle` - A struct type with width and height - `i32` - A primitive integer type - `Option` - A union type that may contain a value **Traits** define behavioral contracts: - `::Addable` - Types that support addition and subtraction - `::Drawable` - Types that can be drawn - `::Stackable` - Types that support stack operations **Key Distinction:** - A value has a type (what it is structurally) - A value implements a trait (how it behaves) - Types are concrete; traits are interfaces - Functions can be generic over traits - Functions can specify types or traits in signatures - Every operator must be backed by a trait **Examples**: ``` // Point is a type (T T --) { x: y: } ::Point struct // Addable is a trait { (Self Self -- Self) +: (Self Self -- Self) -: } ::Addable trait // Point implements Addable (Point now behaves additively) ::Addable { (Self Self -- Self) { over ::x get over ::x get + swap ::y get swap ::y get + Point } +: // ... subtract implementation ... } ::Point impl ``` > **Related**: See Section 9 for the complete trait system and Appendix B for all standard trait definitions. ### 8.2 Type Inference The compiler infers types in most situations, minimizing the need for explicit type annotations. **When Type Inference Works**: ``` 42 // Inferred as i64 (default integer) 3.14 // Inferred as f64 (default float) [1 2 3] // Inferred as array of i64 // Function return type inferred from body (Number -- Number) { dup * } ::square fn 5 square // Compiler knows result is Number ``` **When Annotations Are Needed**: ``` 42:i32 // Explicit annotation for 32-bit integer 3.14:f32 // Explicit annotation for 32-bit float // Ambiguous generic contexts may need hints parse // May need type context to know what to parse to ``` **Type Inference with Generics**: ``` // Type parameter T is inferred from usage (T -- T) { } ::identity fn 5 identity // T inferred as i64 "hello" identity // T inferred as String ``` > **Related**: See Section 10 for generic programming and type parameter inference. ### 8.3 Type Tuples Type tuples represent stack effects and are used in function signatures to specify what a function consumes from and produces to the stack. **Syntax**: `(inputs -- outputs)` **Examples**: ``` (T T -- T) // Two inputs of type T, one output of type T (i32 f64 -- String) // Takes i32 and f64, returns String (-- bool) // No inputs, returns bool (Point --) // Takes Point, no outputs (---) // No inputs, no outputs (side effects only) ``` **Variable Arguments with Iterable**: For operations that need variable numbers of arguments, use the `Iterable` trait: ``` (-- Size) depth: // Zero arguments, returns stack depth (String Iterable --) printf: // String plus iterable of printable values (Iterable -- T) sum: // Iterable of values, returns sum ``` **Examples**: ``` "x=%d, y=%d" [x y] printf // Format string with array of values [1 2 3 4 5] sum // Sum array of numbers depth print // No arguments needed ``` This approach keeps the type system simple without special variadic syntax. ### 8.4 Type Composition Types can contain other types, creating composite data structures: **Nested Structures**: ``` // Point contains two T values (T T --) { x: y: } ::Point struct // Line contains two Points (Point Point --) { start: end: } ::Line struct ``` **Arrays of Types**: ``` [1 2 3] // Array of i64 [[1 2] [3 4]] // Array of arrays [Point Point Point] // Array of Points ``` **Generic Composition**: ``` // Box contains a value of any type (T --) { value: } ::Box struct // Option can contain any type (or nothing) (T --) { Some(T) None } ::Option union // Nested generics Option> // Option containing a Point of f64s ``` ---