Home
Pragmatic functional programming for Python 3.13+
PyPI · GitHub · Get Started
What is Functional Programming?¶
Functional programming is a way of writing code where you build programs by composing pure functions. Functions that always return the same output for the same input and don't modify anything outside themselves.
This sounds abstract, but it solves real problems:
- Bugs from shared state: When multiple parts of your code modify the same data, tracking down bugs becomes a nightmare. Pure functions don't modify anything, so this problem disappears.
- Code that's hard to test: Functions with side effects (database calls, API requests, file I/O) need complex mocks to test. Pure functions just need inputs and expected outputs.
- Code that's hard to understand: When a function can do anything—modify globals, call APIs, write files—you have to read the entire implementation to know what it does. Pure functions are predictable.
Functional programming isn't about using fancy abstractions. It's about writing code that's easier to reason about, test, and maintain.
Why fptk?¶
Python is a great language, but it has some pain points that functional patterns solve elegantly:
The None Problem¶
Python's None propagates silently until it explodes. You end up with defensive code everywhere:
user = get_user(id)
if user and user.get("profile") and user.get("profile").get("name"):
name = user["profile"]["name"].upper()
else:
name = "Anonymous"
fptk's Option makes absence explicit and composable:
name = (
from_nullable(get_user(id))
.bind(lambda u: from_nullable(u.get("profile")))
.bind(lambda p: from_nullable(p.get("name")))
.map(str.upper)
.unwrap_or("Anonymous")
)
The Exception Problem¶
Exceptions are invisible in function signatures. You call parse_json(data) and have no idea it might raise JSONDecodeError, UnicodeDecodeError, or MemoryError. You either wrap everything in try/except or hope for the best.
fptk's Result makes errors part of the type:
def parse_json(data: str) -> Result[dict, str]:
...
# The return type tells you: this can fail, handle it
The Nested Calls Problem¶
Real code often looks like this:
Reading order is inside-out. Adding a step means finding the right nesting level. fptk's pipe makes data flow linear:
The Functional Mindset¶
Functional programming asks you to think differently:
| Imperative Thinking | Functional Thinking |
|---|---|
| "Do this, then do that" | "Transform this into that" |
| Modify variables in place | Create new values from old ones |
| Handle errors with try/catch | Make errors part of the return type |
| Check for None everywhere | Make absence explicit with Option |
| Functions can do anything | Functions only compute outputs from inputs |
This shift takes practice, but the payoff is code that's more predictable, testable, and composable.
What fptk Provides¶
| Feature | What it solves |
|---|---|
pipe, compose |
Nested function calls, hard-to-read data flow |
Option |
Null pointer errors, defensive None checks |
Result |
Invisible exceptions, unclear error handling |
validate_all |
Fail-fast validation, poor error messages |
Reader |
Dependency injection, config threading |
State |
Mutable state, hard-to-test stateful code |
Writer |
Logging mixed with logic, side effects |
Installation¶
Next Steps¶
- Getting Started — Understand the concepts and start using fptk
- Guide
- Core Concepts — Deep dive into each pattern
- Side Effects — Structure code with pure cores
- Migration — Gradually adopt functional patterns
- Examples
- API Development — Build robust web APIs
- Data Processing — ETL pipelines and transformations
- Reference — Complete API documentation with theory and examples