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
5.7 KiB
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:
elm repl
Try these expressions:
> 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:
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
{
"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-directoriesis like setting up your bundler's entry pointsdependenciesworks likepackage.jsonbut with direct/indirect separation- Unlike npm, Elm enforces semantic versioning automatically
Hello World
Create src/Main.elm:
module Main exposing (main)
import Html exposing (text)
main =
text "Hello, Elm!"
Let's break this down:
1. Module Declaration
module Main exposing (main)
- Every Elm file is a module
exposing (main)says "makemainavailable to other modules"- JavaScript equivalent:
export { main }
2. Imports
import Html exposing (text)
- Import the
Htmlmodule exposing (text)lets us usetextdirectly instead ofHtml.text- JavaScript equivalent:
import { text } from 'html'
3. The main Function
main =
text "Hello, Elm!"
mainis the entry point (likeReactDOM.renderor your app's root)textcreates an HTML text node- No
returnkeyword needed - the last expression is the return value
Running Your Code
Option 1: Elm Reactor (Development Server)
elm reactor
Open http://localhost:8000 and click on src/Main.elm.
Option 2: Compile to HTML
elm make src/Main.elm
This creates an index.html file you can open in a browser.
Option 3: Elm Live (Hot Reloading)
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:
- Calculate
123 * 456 - Concatenate three strings: "I", " love", " Elm"
- Find the length of "functional programming"
- Try
1 + "hello"- what happens?
Solutions
> 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...
Exercise 1.2: Modify Hello World
- Change the greeting to include your name
- Try using
String.toUpperto make it ALL CAPS
Solution
module Main exposing (main)
import Html exposing (text)
main =
text (String.toUpper "Hello, Your Name!")
Exercise 1.3: Multiple Elements
We need to use Html.div to group multiple elements:
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:
- A heading with your name
- A paragraph about why you're learning Elm
- Another paragraph about your programming background
Solution
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." ]
]
Key Takeaways
- Elm is typed - The compiler tells you types and catches errors early
- No semicolons or braces - Whitespace and indentation matter
- Everything is an expression - No statements, everything returns a value
- String concatenation uses
++- Not+like JavaScript - HTML is just functions -
div,h1,pare 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, 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