Chapter F0 · context, not a prerequisite
Where this came from
This is the map of the course and the story behind it. Elixir did not appear from nowhere: it sits at the end of a long line of ideas about functions and a thirty-year line of work on a fault-tolerant runtime. F0 sketches both, and you can skip it — F1 stands on its own.
The course proper is seven chapters and 59 modules, plus this optional history. If you are arriving from another platform, the onramp below maps what you already know onto the BEAM.
Where should you start?
The course reads in order, but where you join depends on what you bring. Pick the closest fit.
Your background · select one
Coming from C# and .NET?
If your background is the CLR — ASP.NET, EF Core, Task and
async/await — most of Elixir's ideas already have a name in your world. The gap
is the runtime, not the concepts. This onramp walks the difference between the two virtual machines, the
functional features C# has steadily adopted, and the language-ext library that
makes the mapping concrete.
The CLR versus the BEAM, the functional ideas C# already shares, and language-ext — Option, Either, immutable collections, and the actor model — mapped onto Elixir's own.
The history chapter
Two readings trace the two lineages that meet in Elixir — the idea of the function, and the runtime that runs millions of them at once.
- F0.1 · The evolution of functional languages & runtimes — available
- From the lambda calculus to LISP, ML, and Haskell — the lineage of ideas Elixir inherited.
- F0.2 · The evolution of Erlang, the BEAM & OTP — available
- Telecom roots, “let it crash”, the scheduler and per-process heaps — the runtime Elixir stands on.
- Elixir for C# developers — onramp
- The bridge from .NET: runtimes compared, and language-ext as the Rosetta stone.
The full map
The whole course, chapter by chapter. Open any one.
The evolution of functional languages & runtimes
λ-calculus → LISP → ML/Haskell → the immutable turn.
- F0.1.1From λ-calculus to LISP
- F0.1.2Types & laziness — the ML and Haskell branch
- F0.1.3The immutable turn — persistent data on the JVM & CLR
The evolution of Erlang, the BEAM & OTP
Telecom roots, soft-real-time scheduling, and supervision.
- F0.2.1Telecom roots & “let it crash”
- F0.2.2Inside the BEAM — scheduling, heaps & soft-real-time GC
- F0.2.3OTP & the supervision tree — and the polyglot BEAM
What a function really is
Mapping, domain & range, exactly one output → first-class functions.
The substitution model
Equals for equals → referential transparency and purity.
Composition, f∘g
Chaining mappings, associativity → the pipe.
Immutability & binding
A symbol names a fixed value → immutable data.
Sets, sequences & mappings
Applying f across a collection → lists, maps, Enum.map.
Recursion & induction
Base case + step, and the proof → recursion, no loops.
Higher-order operators (Σ, Π)
Operators over functions → map / filter / reduce.
Equations & pattern matching
Identities, solving by structure → pattern matching.
Functions on the plane — a plotting lab
Plot and compose functions; watch f∘g as curves.
Functional Programming
Open chapter →Pure functions, immutability, and higher-order functions on their own terms.
Pure functions & side effects
What purity buys; isolating effects.
Immutability & persistent data
Structural sharing; why copying is cheap.
Higher-order functions
Functions as arguments and return values.
Recursion patterns & tail calls
Accumulators and tail-call optimisation.
map / filter / reduce (folds)
reduce as the universal fold.
Closures & partial application
Capturing environment; & and currying by hand.
Algebraic data types
Sum and product types; tagged tuples.
Composition & pipelines
Building programs by composing functions.
The data-pipeline lab
Compose map/filter/reduce over a dataset; watch each stage.
Values, types & IEx
The data you build with; the shell as a tool.
Pattern matching & the match operator
= is a match, not assignment.
Functions, modules & the pipe
Defining and composing in modules.
Enumerables & streams
Eager versus lazy traversal.
Structs, maps & keyword lists
Shaping data; when to use which.
Protocols & behaviours
Polymorphism and contracts.
Processes & the actor model
spawn, send, receive; isolation.
OTP: GenServer & supervisors
Stateful servers and fault tolerance.
The process playground
Spawn processes, send messages, watch the mailbox live.
Algorithms & Data Structures
Open chapter →Classical and advanced problems, from lists to branded CHAMP tries.
Lists, recursion & complexity
Cons cells; big-O on the BEAM.
Trees & traversals
Binary and n-ary trees; DFS/BFS, functionally.
Sorting & searching
Merge/quick sort and binary search, immutably.
Maps, sets & hashing
Hash maps, collisions, the cost model.
Hash Array Mapped Tries (HAMT)
Persistent maps via prefix trees.
CHAMP maps
Compressed Hash-Array Mapped Prefix-trees; layout & iteration.
Identifiers, Snowflake & branded ids
From naive ids to a Snowflake bigint and a branded, base62 id.
Branded ids & persistence
Branded ids as keys in SQLite, PostgreSQL, and Redis.
Branded CHAMP maps & GenServer
A CHAMP keyed by branded ids, partitioned by namespace, behind a GenServer.
Practical recipes in Elixir
Turning algorithmic problems into idiomatic Elixir.
Dynamic programming & advanced problems
Overlapping subproblems, memoized and tabulated.
Lab: build a branded CHAMP store
An interactive lab: insert branded keys and watch the partitioned CHAMP restructure.
Pragmatic Programming
Open chapter →Real-world engineering: structure, testing, telemetry, releases.
Foundations
Start thin: a running Portal from day one.
Modeling the Portal domain
Bounded contexts, structs, and the public API.
Tracer bullets: a walking skeleton
Thin end-to-end first, then iterate.
Design by contract
Preconditions, postconditions, and failing fast.
Commands, queries & events
Separate writes from reads; the engine as a reducer over events.
Where engine state lives
One process holds the state; one supervisor keeps it alive.
Pragmatic testing
Testing the pure core, property-based tests, and contracts as tests.
Boundaries & integration seams
Ports out, a facade in, one error vocabulary for the UI.
Lab: the Portal engine, LiveView-ready
Assemble the engine end to end, then mount it behind a LiveView.
Architecture & the request lifecycle
endpoint → router → controller → view.
Routing, controllers & plugs
The plug pipeline.
Ecto: schemas, changesets & queries
Data, validation, the repo.
Contexts & domain design
Boundaries that scale.
Templates, components & HEEx
Server-rendered markup.
Phoenix LiveView fundamentals
Interactive UIs without hand-written JS.
PubSub, channels & real-time
Live updates over WebSockets.
Auth, deployment & going live
Sessions, releases, production.
The live dashboard
Real-time LiveView state over a socket; multi-client via PubSub.
Deploy to Fly
Open chapter →Take the Portal live on Fly.io — the four stacked, silent-until-boot deploy gotchas, mastered one module at a time.
The release image
A multi-stage Dockerfile that builds the scoped release and ships every file the runtime needs.
Runtime config & the IPv6 network
runtime.exs at boot; Postgrex over Fly’s IPv6 DNS.
The database goes live
A reachable, migrated Postgres behind the F5 port.
fly.toml & the deploy mechanics
A distilled config; a deploy that rolls and self-heals.
Portal is live
The verified-live endpoint and the day-2 operations.