Files
lux/docs/OVERVIEW.md
Brandon Lucas 086552b7a4 feat: add schema evolution type system integration and HTTP server effect
Schema Evolution:
- Preserve version info in type resolution (Type::Versioned)
- Track versioned type declarations in typechecker
- Detect version mismatches at compile time (@v1 vs @v2 errors)
- Support @v2+ (at least) and @latest version constraints
- Store migrations for future auto-migration support
- Fix let bindings to preserve declared type annotations

HTTP Server Effect:
- Add HttpServer effect with listen, accept, respond, respondWithHeaders, stop
- Implement blocking request handling via tiny_http
- Request record includes method, path, body, headers
- Add http_server.lux example with routing via pattern matching
- Add type-checking test for HttpServer effect

Tests: 222 passing (up from 217)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 22:06:31 -05:00

360 lines
9.6 KiB
Markdown

# Lux Language Overview
## What is Lux?
Lux is a statically-typed functional programming language with **algebraic effects** as a first-class feature. It makes side effects explicit, trackable, and testable.
## What Can You Do With It?
### Currently Working
```lux
// Functions with type inference
fn factorial(n: Int): Int =
if n <= 1 then 1 else n * factorial(n - 1)
// Higher-order functions
fn apply(f: fn(Int): Int, x: Int): Int = f(x)
fn double(x: Int): Int = x * 2
let result = apply(double, 21) // 42
// Lambdas and closures
let add = fn(a: Int, b: Int): Int => a + b
let addFive = fn(x: Int): Int => add(5, x)
// Pattern matching
fn describe(n: Int): String =
match n {
0 => "zero",
1 => "one",
_ => "many"
}
// Records
let person = { name: "Alice", age: 30 }
let age = person.age
// Tuples
let point = (10, 20)
// Lists
let numbers = [1, 2, 3, 4, 5]
// Pipe operator
let result = 5 |> double |> addOne // (5 * 2) + 1 = 11
// Built-in effects (Console, Fail)
Console.print("Hello, world!")
// Custom effects
effect Logger {
fn log(level: String, msg: String): Unit
}
// Effect handlers
handler consoleLogger: Logger {
fn log(level, msg) = Console.print("[" + level + "] " + msg)
}
// Running with handlers
fn greet(name: String): Unit with {Logger} =
Logger.log("info", "Hello, " + name)
run greet("Alice") with { Logger = consoleLogger }
```
### Standard Library (Built-in)
```lux
// List operations
List.map([1, 2, 3], fn(x: Int): Int => x * 2) // [2, 4, 6]
List.filter([1, 2, 3, 4], fn(x: Int): Bool => x > 2) // [3, 4]
List.fold([1, 2, 3], 0, fn(acc: Int, x: Int): Int => acc + x) // 6
List.head([1, 2, 3]) // Some(1)
List.tail([1, 2, 3]) // Some([2, 3])
List.concat([1, 2], [3]) // [1, 2, 3]
List.reverse([1, 2, 3]) // [3, 2, 1]
List.length([1, 2, 3]) // 3
List.get([1, 2, 3], 0) // Some(1)
List.range(0, 5) // [0, 1, 2, 3, 4]
// String operations
String.split("a,b,c", ",") // ["a", "b", "c"]
String.join(["a", "b"], "-") // "a-b"
String.trim(" hello ") // "hello"
String.contains("hello", "ell") // true
String.replace("hi", "i", "ey") // "hey"
String.length("hello") // 5
String.chars("hi") // ['h', 'i']
String.lines("a\nb") // ["a", "b"]
// Option operations
let x = Some(42)
let y = None
Option.map(x, fn(n: Int): Int => n * 2) // Some(84)
Option.flatMap(x, fn(n: Int): Option<Int> => Some(n + 1)) // Some(43)
Option.getOrElse(y, 0) // 0
Option.isSome(x) // true
Option.isNone(y) // true
// Result operations
let ok = Ok(42)
let err = Err("failed")
Result.map(ok, fn(n: Int): Int => n * 2) // Ok(84)
Result.getOrElse(err, 0) // 0
Result.isOk(ok) // true
Result.isErr(err) // true
// Utility functions
print("Hello") // prints to stdout
toString(42) // "42"
typeOf([1, 2, 3]) // "List"
```
### Also Working
```lux
// Generic type parameters
fn map<T, U>(f: fn(T): U, list: List<T>): List<U> = ...
fn identity<T>(x: T): T = x
// String interpolation
let name = "Alice"
Console.print("Hello, {name}!") // Hello, Alice!
Console.print("1 + 2 = {1 + 2}") // 1 + 2 = 3
// File effects
let content = File.read("config.txt")
File.write("output.txt", "Hello!")
let exists = File.exists("file.lux")
// HTTP client effects
let response = Http.get("https://api.example.com/data")
Http.post("https://api.example.com/submit", "{\"key\": \"value\"}")
// HTTP server effects
HttpServer.listen(8080)
let req = HttpServer.accept() // Returns { method, path, body, headers }
HttpServer.respond(200, "Hello, World!")
HttpServer.stop()
// Random effects
let n = Random.int(1, 100)
let coin = Random.bool()
// Time effects
let now = Time.now()
Time.sleep(1000) // milliseconds
// JSON parsing
let obj = Json.parse("{\"name\": \"Alice\"}")
let str = Json.stringify(obj)
// Module system
import mymodule
import utils/helpers as h
import math.{sqrt, abs}
import prelude.*
```
### Planned (Not Yet Fully Implemented)
- **Schema Evolution**: Parsing works (`@v1`, `from @v1`), type system integration missing
- **Behavioral Types**: Parsing works (`is pure`, `is total`), verification beyond `pure` missing
- **Full Compilation**: JIT works for numeric code, strings/lists/ADTs missing
---
## Primary Use Cases
### 1. Learning Effect Systems
Lux is an excellent educational tool for understanding algebraic effects without the complexity of Haskell's monad transformers or the academic syntax of languages like Koka.
### 2. Testable Application Code
Effects make dependencies explicit. Swap handlers for testing:
```lux
// Production
run app() with { Database = postgres, Http = realHttp }
// Testing
run app() with { Database = mockDb, Http = mockHttp }
```
### 3. Domain Modeling
Explicit effects document what code can do:
```lux
fn processOrder(order: Order): Receipt with {Database, Email, Logger}
// ^ The signature tells you exactly what side effects this function performs
```
### 4. Prototyping
Quick iteration with type inference and a REPL.
---
## Pros and Cons
### Pros
| Advantage | Description |
|-----------|-------------|
| **Explicit Effects** | Function signatures show what side effects are possible |
| **Testability** | Swap effect handlers for mocking—no dependency injection frameworks |
| **Type Safety** | Static types catch errors at compile time |
| **Type Inference** | Write less type annotations, compiler figures it out |
| **Clean Syntax** | ML-family inspired, minimal boilerplate |
| **Pattern Matching** | Destructure data elegantly |
| **Immutable by Default** | Easier to reason about |
| **REPL** | Interactive development |
### Cons
| Limitation | Description |
|------------|-------------|
| **Limited JIT** | Cranelift JIT works for numeric code only |
| **No Package Manager** | Can't share/publish packages yet |
| **New Paradigm** | Effects require learning new concepts |
| **Small Ecosystem** | No community packages yet |
| **Early Stage** | Bugs likely, features incomplete |
---
## Complexity Assessment
### Conceptual Complexity
| Concept | Difficulty | Notes |
|---------|------------|-------|
| Basic syntax | Easy | Similar to other ML-family languages |
| Functions | Easy | Standard functional style |
| Pattern matching | Easy | If you know any FP language |
| Type system | Medium | Hindley-Milner inference helps |
| Effects | Medium | New concept, but simpler than monads |
| Handlers | Medium | Requires understanding of continuations |
### Comparison to Other Languages
| Language | Complexity | Comparison to Lux |
|----------|------------|-------------------|
| Python | Simpler | No types, no effect tracking |
| TypeScript | Similar | Lux has effects, TS has larger ecosystem |
| Elm | Similar | Both pure FP, Lux has general effects |
| Haskell | More Complex | Monads harder than algebraic effects |
| Koka | Similar | Koka more academic, Lux more practical syntax |
| Rust | More Complex | Ownership adds significant complexity |
### Learning Curve
**Beginner** (1-2 hours):
- Basic expressions, functions, let bindings
- If/else, pattern matching
- REPL usage
**Intermediate** (1-2 days):
- Custom types and records
- Higher-order functions
- Built-in effects (Console)
**Advanced** (1 week):
- Custom effect definitions
- Effect handlers
- Understanding when to use effects vs. regular functions
---
## When to Use Lux
### Good Fit
- Learning algebraic effects
- Prototyping with explicit effect tracking
- Small tools where testability matters
- Teaching functional programming concepts
### Not a Good Fit (Yet)
- Large production applications (early stage)
- Performance-critical code (JIT limited to numeric)
- Web frontend development (no JS compilation)
- Systems programming (no low-level control)
---
## Example Session
```
$ cargo run
Lux v0.1.0
Type :help for help, :quit to exit
lux> let x = 42
lux> x * 2
84
lux> fn greet(name: String): Unit with {Console} = Console.print("Hello, " + name)
lux> greet("World")
Hello, World
()
lux> let nums = [1, 2, 3]
lux> nums
[1, 2, 3]
lux> :quit
```
---
## Architecture
```
Source Code
┌─────────┐
│ Lexer │ → Tokens
└─────────┘
┌─────────┐
│ Parser │ → AST
└─────────┘
┌─────────────┐
│ Type Checker│ → Typed AST + Effect Tracking
└─────────────┘
├─────────────────────────┐
▼ ▼
┌─────────────┐ ┌──────────────┐
│ Interpreter │ │ JIT Compiler │
│ (default) │ │ (Cranelift) │
└─────────────┘ └──────────────┘
│ │
▼ ▼
Values + Effects Native Code
(~160x speedup)
```
---
## Future Roadmap
**Complete:**
- ✅ Standard Library (List, String, Option, Result, JSON)
- ✅ Module System (imports, exports, aliases)
- ✅ LSP Server (basic diagnostics, hover, completions)
- ✅ Generics and String Interpolation
- ✅ File/HTTP/Random/Time Effects
**In Progress:**
1. **Behavioral Type Verification** - Total, idempotent, deterministic checking
2. **Schema Evolution** - Type system integration, auto-migration
3. **Error Message Quality** - Elm-style suggestions
**Planned:**
4. **HTTP Server Effect** - Build web APIs
5. **SQL Effect** - Database access
6. **Package Manager** - Share code
7. **JavaScript Backend** - Run in browsers