Initial commit: Elm tutorial for JavaScript developers

This tutorial includes:
- 7 progressive lessons covering Elm fundamentals
- Exercises with starter code
- Solutions for exercises
- Final project: Task Manager app with localStorage persistence

Topics covered:
- Basic syntax and types
- Functions and functional programming concepts
- The Elm Architecture (Model-View-Update)
- Lists and Maybe types
- HTTP requests and JSON decoding
- Ports for JavaScript interop
This commit is contained in:
2026-03-11 11:07:15 +00:00
commit 7d7986f3ab
16 changed files with 5342 additions and 0 deletions

274
lessons/01-introduction.md Normal file
View File

@@ -0,0 +1,274 @@
# Lesson 1: Introduction & Your First Elm Program
## Learning Goals
By the end of this lesson, you will:
- Understand the Elm REPL
- Create your first Elm project
- Compile and run Elm code
- Understand the project structure
## The Elm REPL
Like Node.js, Elm has a REPL (Read-Eval-Print Loop) for experimenting with code.
Start it by running:
```bash
elm repl
```
Try these expressions:
```elm
> 1 + 1
2 : number
> "Hello" ++ " World"
"Hello World" : String
> String.length "Elm"
3 : Int
```
Notice something different from JavaScript? Elm tells you the **type** of each result!
### Key Differences from JavaScript Console
| JavaScript | Elm REPL |
|-----------|----------|
| `"a" + "b"` | `"a" ++ "b"` (string concat uses `++`) |
| `1 + "1"` = `"11"` | Error! Can't mix types |
| `console.log(x)` | Just type the expression |
Type `:exit` to leave the REPL.
## Your First Elm Project
Let's create a real project:
```bash
mkdir hello-elm
cd hello-elm
elm init
```
This creates:
```
hello-elm/
├── elm.json # Project configuration (like package.json)
└── src/ # Your Elm source files go here
```
### Understanding elm.json
```json
{
"type": "application",
"source-directories": ["src"],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0"
},
"indirect": { ... }
},
"test-dependencies": { ... }
}
```
**Comparison to JavaScript:**
- `source-directories` is like setting up your bundler's entry points
- `dependencies` works like `package.json` but with direct/indirect separation
- Unlike npm, Elm enforces **semantic versioning automatically**
## Hello World
Create `src/Main.elm`:
```elm
module Main exposing (main)
import Html exposing (text)
main =
text "Hello, Elm!"
```
Let's break this down:
### 1. Module Declaration
```elm
module Main exposing (main)
```
- Every Elm file is a **module**
- `exposing (main)` says "make `main` available to other modules"
- **JavaScript equivalent:** `export { main }`
### 2. Imports
```elm
import Html exposing (text)
```
- Import the `Html` module
- `exposing (text)` lets us use `text` directly instead of `Html.text`
- **JavaScript equivalent:** `import { text } from 'html'`
### 3. The main Function
```elm
main =
text "Hello, Elm!"
```
- `main` is the entry point (like `ReactDOM.render` or your app's root)
- `text` creates an HTML text node
- No `return` keyword needed - the last expression is the return value
## Running Your Code
### Option 1: Elm Reactor (Development Server)
```bash
elm reactor
```
Open http://localhost:8000 and click on `src/Main.elm`.
### Option 2: Compile to HTML
```bash
elm make src/Main.elm
```
This creates an `index.html` file you can open in a browser.
### Option 3: Elm Live (Hot Reloading)
```bash
elm-live src/Main.elm -- --open
```
This opens your browser and reloads on file changes (like webpack-dev-server).
## Exercise 1.1: Experiment in the REPL
Start `elm repl` and try:
1. Calculate `123 * 456`
2. Concatenate three strings: "I", " love", " Elm"
3. Find the length of "functional programming"
4. Try `1 + "hello"` - what happens?
<details>
<summary>Solutions</summary>
```elm
> 123 * 456
56088 : number
> "I" ++ " love" ++ " Elm"
"I love Elm" : String
> String.length "functional programming"
22 : Int
> 1 + "hello"
-- TYPE MISMATCH --
The (+) operator is expecting both arguments to be numbers...
```
</details>
## Exercise 1.2: Modify Hello World
1. Change the greeting to include your name
2. Try using `String.toUpper` to make it ALL CAPS
<details>
<summary>Solution</summary>
```elm
module Main exposing (main)
import Html exposing (text)
main =
text (String.toUpper "Hello, Your Name!")
```
</details>
## Exercise 1.3: Multiple Elements
We need to use `Html.div` to group multiple elements:
```elm
module Main exposing (main)
import Html exposing (div, h1, p, text)
main =
div []
[ h1 [] [ text "Welcome to Elm" ]
, p [] [ text "This is a paragraph" ]
]
```
The pattern is: `element attributes children`
- `div []` - a div with no attributes
- `[ h1 ..., p ... ]` - list of children
Create a page with:
1. A heading with your name
2. A paragraph about why you're learning Elm
3. Another paragraph about your programming background
<details>
<summary>Solution</summary>
```elm
module Main exposing (main)
import Html exposing (div, h1, p, text)
main =
div []
[ h1 [] [ text "Hi, I'm Learning Elm!" ]
, p [] [ text "I want to learn functional programming." ]
, p [] [ text "I have experience with JavaScript." ]
]
```
</details>
## Key Takeaways
1. **Elm is typed** - The compiler tells you types and catches errors early
2. **No semicolons or braces** - Whitespace and indentation matter
3. **Everything is an expression** - No statements, everything returns a value
4. **String concatenation uses `++`** - Not `+` like JavaScript
5. **HTML is just functions** - `div`, `h1`, `p` are all functions
## Common Mistakes from JavaScript Developers
| Mistake | Why It Happens | Elm Way |
|---------|---------------|---------|
| Using `+` for strings | JavaScript habit | Use `++` |
| Forgetting type annotations | JS doesn't have them | Optional but recommended |
| Using `return` | JS function habit | Last expression is returned |
| Using `{}` for blocks | JS syntax | Use indentation |
## What's Next?
In [Lesson 2](02-basics.md), we'll dive deeper into Elm's type system and learn about:
- Primitive types (Int, Float, String, Bool)
- Type annotations
- Records (like JavaScript objects, but better!)
- Custom types
---
[Next: Lesson 2 - Basic Syntax & Types →](02-basics.md)