# 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:

```lux
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):

```lux
let pi = 3.14159
let e = 2.718

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

### Bool

Boolean values:

```lux
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:

```lux
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:

```lux
let letter = 'A'
let emoji = '🎉'
```

### Unit

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

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

let nothing: Unit = ()
```

## Type Annotations

Usually optional, but sometimes helpful:

```lux
// 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:

```lux
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:

```lux
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:

```lux
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:

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

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

## Records

Named fields:

```lux
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

```lux
// 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:

```lux
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](03-functions.md) - Learn to define and compose functions.
