Course Orientation — Why This Series Exists¶
Functional programming in Python is often presented as a grab-bag of tricks. This series takes a correctness-first, production-focused path instead: you will build and evolve a real FuncPipe RAG pipeline while learning how to reason about purity, effects, streaming, async backpressure, and domain modelling without magic. Module 00 is your map, expectations, and setup checklist before you start writing code.
Who This Is For¶
- You ship Python services, data pipelines, or ML workflows and need predictable, testable behavior under change and load.
- You know Python well (classes, typing, packaging) and want FP tools without category-theory detours.
- You want patterns that survive refactoring, concurrency, and production debugging, not just cute one-liners.
How to Use the Course Book¶
- Read, then run. Every module pairs narrative with runnable code in
src/andtests/. Apply ideas to the evolving FuncPipe RAG project. - Keep effects at the edges. Expect constant reminders to isolate I/O; you will refactor toward purity, not away from it.
- Treat claims as contracts. Assertions and property tests back the concepts; extend them when you adapt patterns to your codebase.
- Use the docs locally.
make docs-serverenders this book (Material theme) and supports live reloading while you edit or experiment.
Progression Map (10 Modules)¶
| Module | Focus | What You Gain |
|---|---|---|
| 01 | Pure functions & substitution | Spot impurities, refactor to pure call graphs, prove equivalence with Hypothesis |
| 02 | Closures & expression style | Partial application, data-first APIs, configuration-as-data, debugging compositions |
| 03 | Iterators & laziness | Streaming pipelines, chunking, safe fan-in/out, observability on lazy flows |
| 04 | Recursion, folds, resilience | Memoization, Result/Option for per-record failures, structured error aggregation |
| 05 | Algebraic data modelling | ADTs, functors/applicatives, monoids, Pydantic edges, serialization contracts |
| 06 | Monadic flows | bind/and_then, layered containers, Reader/State patterns, configurable pipelines |
| 07 | Effect boundaries | Ports/adapters, capability protocols, idempotent effect design, resource safety |
| 08 | Async + backpressure | Async generators, bounded queues, retry/timeout policies as data, rate limiting |
| 09 | Ecosystem interop | Stdlib/toolz/returns facades, dataframes in FP style, config-driven pipeline specs |
| 10 | Refactoring & sustainment | Systematic migration, performance budgets, property-based regression, governance |
Module 00 keeps you oriented; Modules 01–10 are the build-up; the repository state matches the end of Module 09, and you will keep refactoring it as you learn.
What “Progress” Looks Like¶
- Conceptual: You can state the law or invariant in one sentence (e.g., referential transparency), and explain when to violate it.
- Practical: You have a small, runnable diff that proves the idea on the FuncPipe RAG code (or your own code).
- Testing: You write at least one property test or contract check per module to keep changes honest.
- Operational: You know where side effects live and can trace them with logs/metrics without breaking purity in the core.
Track your progress by annotating the module markdowns or adding small “checkpoint” tests in tests/ as you finish each core.
Setup Checklist (Before Module 01)¶
- Create a fresh virtualenv:
python3 -m venv .venv && source .venv/bin/activate. - Install dev + docs tooling:
make install(orpip install -e '.[dev,docs]'). - Run the doc server:
make docs-serveand open the local URL for live updates. - Run tests to ensure baseline correctness:
make test. - Skim
README.mdfor the current project shape and module progression notes.
If anything fails here, fix it now—later modules assume this baseline works.
How to Read Each Module¶
- Start with the core question at the top of each module—know what you must be able to answer.
- Work through examples in order, running them in a REPL or test; avoid jumping ahead to async or ADTs before nailing purity.
- Mirror each pattern in your own code (e.g., isolate I/O, swap mutable globals for explicit parameters).
- Leave behind evidence: a property test, a small refactor, or a note on when a pattern should not be used.
What You’ll Notice in the Style¶
- Data-first APIs: Functions accept data and return new data; side effects are explicitly threaded.
- Small, composable helpers: Prefer tiny combinators and clear contracts over clever one-liners.
- Evidence over assertion: Every claim should have a runnable snippet or property.
- Production realism: Logging, retries, backpressure, and type boundaries show up early.
Carry this mindset into every module; it keeps the growing FuncPipe RAG pipeline understandable and testable.