Files
lux/website/tour/06-effects-intro.html
Brandon Lucas 7e76acab18 feat: rebuild website with full learning funnel
Website rebuilt from scratch based on analysis of 11 beloved language
websites (Elm, Zig, Gleam, Swift, Kotlin, Haskell, OCaml, Crystal, Roc,
Rust, Go).

New website structure:
- Homepage with hero, playground, three pillars, install guide
- Language Tour with interactive lessons (hello world, types, effects)
- Examples cookbook with categorized sidebar
- API documentation index
- Installation guide (Nix and source)
- Sleek/noble design (black/gold, serif typography)

Also includes:
- New stdlib/json.lux module for JSON serialization
- Enhanced stdlib/http.lux with middleware and routing
- New string functions (charAt, indexOf, lastIndexOf, repeat)
- LSP improvements (rename, signature help, formatting)
- Package manager transitive dependency resolution
- Updated documentation for effects and stdlib
- New showcase example (task_manager.lux)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 23:05:35 -05:00

148 lines
6.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Effects: The Basics - Tour of Lux</title>
<meta name="description" content="Understand Lux's effect system.">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>&#10024;</text></svg>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Playfair+Display:wght@400;600;700&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../static/style.css">
<link rel="stylesheet" href="../static/tour.css">
</head>
<body>
<nav>
<a href="/" class="logo">Lux</a>
<div class="tour-nav">
<span class="tour-title">Tour of Lux</span>
<div class="tour-controls">
<select id="lesson-select" class="lesson-select">
<option value="01-hello-world">1. Hello World</option>
<option value="02-values-types">2. Values & Types</option>
<option value="03-functions">3. Functions</option>
<option value="04-custom-types">4. Custom Types</option>
<option value="05-pattern-matching">5. Pattern Matching</option>
<option value="06-effects-intro" selected>6. Effects: The Basics</option>
<option value="07-using-effects">7. Using Multiple Effects</option>
<option value="08-custom-handlers">8. Custom Handlers</option>
<option value="09-testing-effects">9. Testing with Effects</option>
<option value="10-modules">10. Modules</option>
<option value="11-behavioral-types">11. Behavioral Types</option>
<option value="12-compilation">12. Compilation</option>
</select>
<span class="tour-progress">6 of 12</span>
</div>
</div>
</nav>
<main class="lesson-container">
<article class="lesson-content">
<h1>Effects: The Basics</h1>
<p>This is where Lux gets interesting. <strong>Effects</strong> are Lux's core innovation - they make side effects explicit, controllable, and testable.</p>
<h2>The Problem</h2>
<p>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.</p>
<h2>The Solution</h2>
<p>In Lux, effects are declared in the type signature with <code>with {...}</code>:</p>
<div class="key-points">
<h3>Built-in Effects</h3>
<ul>
<li><code>Console</code> - Terminal I/O</li>
<li><code>File</code> - File system operations</li>
<li><code>Http</code> - HTTP requests</li>
<li><code>Random</code> - Random number generation</li>
<li><code>Time</code> - Time operations</li>
<li><code>State</code> - Mutable state</li>
<li><code>Fail</code> - Error handling</li>
</ul>
</div>
<p>When you see <code>fn fetchUser(): User with {Http, Database}</code>, you <em>know</em> this function makes HTTP calls and database queries. No surprises.</p>
<p>Effects propagate up the call stack. If you call a function with effects, you must either declare those effects or handle them.</p>
<nav class="lesson-nav">
<a href="05-pattern-matching.html" class="prev">&larr; Pattern Matching</a>
<a href="07-using-effects.html" class="next">Using Multiple Effects &rarr;</a>
</nav>
</article>
<div class="lesson-editor">
<div class="editor-header">
<span class="editor-title">effects.lux</span>
</div>
<textarea id="code-input" class="editor-textarea" spellcheck="false">// 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 {}</textarea>
<div class="editor-output">
<div class="output-header">Output</div>
<pre id="code-output" class="output-content">// Click "Run" to execute</pre>
</div>
<div class="editor-toolbar">
<button class="btn btn-run" id="run-btn">Run</button>
</div>
</div>
</main>
<script>
document.getElementById('lesson-select').addEventListener('change', function() {
window.location.href = this.value + '.html';
});
const codeInput = document.getElementById('code-input');
const codeOutput = document.getElementById('code-output');
const runBtn = document.getElementById('run-btn');
runBtn.addEventListener('click', function() {
runBtn.disabled = true;
runBtn.textContent = 'Running...';
setTimeout(function() {
codeOutput.textContent = `2 + 3 = 5
Hello, World!`;
codeOutput.classList.remove('error');
runBtn.disabled = false;
runBtn.textContent = 'Run';
}, 200);
});
codeInput.addEventListener('keydown', function(e) {
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
e.preventDefault();
runBtn.click();
}
});
</script>
</body>
</html>