Files
lux/docs/guide/02-basic-types.md
Brandon Lucas 44f88afcf8 docs: add comprehensive language documentation
Documentation structure inspired by Rust Book, Elm Guide, and others:

Guide (10 chapters):
- Introduction and setup
- Basic types (Int, String, Bool, List, Option, Result)
- Functions (closures, higher-order, composition)
- Data types (ADTs, pattern matching, records)
- Effects (the core innovation)
- Handlers (patterns and techniques)
- Modules (imports, exports, organization)
- Error handling (Fail, Option, Result)
- Standard library reference
- Advanced topics (traits, generics, optimization)

Reference:
- Complete syntax reference

Tutorials:
- Calculator (parsing, evaluation, REPL)
- Dependency injection (testing with effects)
- Project ideas (16 projects by difficulty)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 17:43:41 -05:00

4.7 KiB

Chapter 2: Basic Types

Lux is statically typed with full type inference. You rarely need to write types—the compiler figures them out—but understanding them helps.

Primitive Types

Int

64-bit signed integers:

let x = 42
let y = -17
let big = 9_223_372_036_854_775_807  // Underscores for readability

// Arithmetic
x + y    // 25
x - y    // 59
x * y    // -714
x / y    // -2 (integer division)
x % y    // 8 (remainder)

Float

64-bit floating point (IEEE 754):

let pi = 3.14159
let e = 2.718

pi * 2.0    // 6.28318
e / 2.0     // 1.359

Bool

Boolean values:

let yes = true
let no = false

// Operators
true && false   // false (and)
true || false   // true (or)
!true           // false (not)

// Comparison
5 > 3           // true
5 == 5          // true
5 != 3          // true
5 <= 5          // true

String

UTF-8 strings:

let greeting = "Hello"
let name = "World"

// Concatenation
greeting + ", " + name + "!"    // "Hello, World!"

// String interpolation
let message = "The answer is ${40 + 2}"  // "The answer is 42"

// Multiline
let poem = "
    Roses are red,
    Violets are blue,
    Lux has effects,
    And so can you.
"

Char

Single Unicode characters:

let letter = 'A'
let emoji = '🎉'

Unit

The type with only one value, (). Used when a function doesn't return anything meaningful:

fn printHello(): Unit with {Console} =
    Console.print("Hello")

let nothing: Unit = ()

Type Annotations

Usually optional, but sometimes helpful:

// Inferred
let x = 42          // Int
let s = "hello"     // String

// Explicit
let x: Int = 42
let s: String = "hello"

// Required when ambiguous
let empty: List<Int> = []

Lists

Ordered collections of the same type:

let numbers = [1, 2, 3, 4, 5]
let words = ["hello", "world"]
let empty: List<Int> = []

// Operations (from List module)
List.length(numbers)              // 5
List.head(numbers)                // Some(1)
List.tail(numbers)                // [2, 3, 4, 5]
List.map(numbers, fn(x: Int): Int => x * 2)  // [2, 4, 6, 8, 10]
List.filter(numbers, fn(x: Int): Bool => x > 2)  // [3, 4, 5]
List.fold(numbers, 0, fn(acc: Int, x: Int): Int => acc + x)  // 15

Option

For values that might not exist:

let some_value: Option<Int> = Some(42)
let no_value: Option<Int> = None

// Pattern matching
fn describe(opt: Option<Int>): String =
    match opt {
        Some(n) => "Got: " + toString(n),
        None => "Nothing"
    }

// Option operations
Option.map(Some(5), fn(x: Int): Int => x * 2)  // Some(10)
Option.map(None, fn(x: Int): Int => x * 2)     // None
Option.getOrElse(Some(5), 0)                    // 5
Option.getOrElse(None, 0)                       // 0

Result

For operations that can fail:

let success: Result<Int, String> = Ok(42)
let failure: Result<Int, String> = Err("Something went wrong")

// Pattern matching
fn handle(r: Result<Int, String>): String =
    match r {
        Ok(n) => "Success: " + toString(n),
        Err(e) => "Error: " + e
    }

// Result operations
Result.map(Ok(5), fn(x: Int): Int => x * 2)     // Ok(10)
Result.map(Err("oops"), fn(x: Int): Int => x * 2)  // Err("oops")

Tuples

Fixed-size collections of different types:

let pair = (1, "hello")
let triple = (true, 42, "world")

// Access by pattern matching
let (x, y) = pair
// x = 1, y = "hello"

Records

Named fields:

let person = { name: "Alice", age: 30 }

// Access
person.name    // "Alice"
person.age     // 30

// With type annotation
type Person = { name: String, age: Int }
let bob: Person = { name: "Bob", age: 25 }

Type Conversion

// To String
toString(42)        // "42"
toString(true)      // "true"
toString([1,2,3])   // "[1, 2, 3]"

// String to Int (via Console effect)
let n = Console.readInt()

Type Checking

The compiler catches type errors:

let x: Int = "hello"  // Error: expected Int, got String

fn add(a: Int, b: Int): Int = a + b
add(1, "two")  // Error: expected Int, got String

let nums = [1, 2, "three"]  // Error: list elements must have same type

Summary

Type Example Description
Int 42 64-bit integer
Float 3.14 64-bit float
Bool true Boolean
String "hello" UTF-8 string
Char 'A' Unicode character
Unit () No meaningful value
List<T> [1, 2, 3] Ordered collection
Option<T> Some(42) Optional value
Result<T, E> Ok(42) Success or failure
(A, B) (1, "hi") Tuple
{...} {x: 1} Record

Next

Chapter 3: Functions - Learn to define and compose functions.