# Effects: The Basics

This is where Lux gets interesting. Effects are Lux's core innovation - they make side effects explicit, controllable, and testable.

## The Problem

In most languages, any function can do anything - read files, make network calls, modify global state. You can't tell from the signature. You have to read the implementation.

## The Solution

In Lux, effects are declared in the type signature with `with {...}`:

### Built-in Effects

- `Console` - Terminal I/O
- `File` - File system operations
- `Http` - HTTP requests
- `Random` - Random number generation
- `Time` - Time operations
- `State` - Mutable state
- `Fail` - Error handling

When you see `fn fetchUser(): User with {Http, Database}`, you know this function makes HTTP calls and database queries. No surprises.

Effects propagate up the call stack. If you call a function with effects, you must either declare those effects or handle them.

effects.lux
// Pure function - no effects fn add(a: Int, b: Int): Int = a + b // Effectful function - uses Console fn greet(name: String): Unit with {Console} = { Console.print("Hello, " + name + "!") } // Multiple effects fn fetchAndLog(url: String): String with {Http, Console} = { Console.print("Fetching: " + url) let data = Http.get(url) Console.print("Got " + toString(String.length(data)) + " bytes") data } fn main(): Unit with {Console} = { // Pure function - can call anywhere let sum = add(2, 3) Console.print("2 + 3 = " + toString(sum)) // Effectful function - must handle effects greet("World") } run main() with {}
Output

    // Click "Run" to execute