What is better-py?
Learn about better-py's philosophy and approach to functional programming in Python
What is better-py?
better-py is a pragmatic, type-safe functional programming library for Python that brings functional programming concepts to Python in a way that feels natural and idiomatic.
Philosophy
better-py is built on the principle of "Functional Entities as Objects". Instead of using standalone functions, we represent functional concepts as objects with methods. This approach:
- Feels natural to Python developers - Works like the Python objects you already know
- Enables method chaining - Write expressive code like
value.map().filter().reduce() - Provides full type safety - Complete generic type tracking with mypy support
- Maintains immutability - All operations return new instances
Core Principles
1. Objects, Not Functions
Unlike traditional functional programming libraries that use functions, better-py uses objects:
# Traditional functional style (not better-py)
map(lambda x: x * 2, filter(lambda x: x > 0, values))
# better-py style
Some(42).map(lambda x: x * 2)2. Protocol-Based Design
better-py uses Python's typing.Protocol for structural typing. Classes can implement functional behaviors by adhering to protocols, without rigid inheritance hierarchies.
3. Type Safety
Every operation preserves type information through generic type parameters:
from better_py import Some
value: Some[int] = Some(42)
doubled: Some[int] = value.map(lambda x: x * 2) # Type: Some[int]4. Immutability
All entities are frozen dataclasses. Operations return new instances:
original = Some(42)
modified = original.map(lambda x: x * 2)
# original is still Some(42)
# modified is Some(84)What's Included
Monads
- Maybe[T] - Handle optional values (
Some(value)orNothing) - Result[T, E] - Explicit error handling (
Ok(value)orError(error)) - Either[L, R] - Two-value alternatives (
LeftorRight) - Validation[T, E] - Accumulate validation errors (
ValidorInvalid) - IO - Delay side effects
- Reader - Dependency injection
- Writer - Logging and accumulation
- State - State threading
- Try - Exception handling as values
Protocols
- Mappable - Functor-like map operations
- Reducible - Fold/reduce operations
- Combinable - Monoid combine operations
- Traversable - Sequence operations
- Updatable - Immutable updates
Collections
- PersistentList - Immutable linked list with structural sharing
- PersistentMap - Immutable dictionary
- PersistentSet - Immutable set
Utilities
- pipe - Left-to-right function composition
- compose - Right-to-left function composition
- curry - Partial application
- partial_right - Right-side partial application
Who Should Use better-py?
better-py is ideal for Python developers who want to:
- Write more robust code with explicit error handling
- Eliminate null/None errors with Maybe
- Compose operations cleanly with method chaining
- Maintain type safety with full mypy support
- Learn functional programming in a Pythonic way
What better-py is NOT
- ❌ Not a framework - It's a library you can use anywhere
- ❌ Not academic - Avoids confusing terminology, focuses on practicality
- ❌ Not opinionated - Use what you need, ignore what you don't
- ❌ Not incompatible - Works well with existing Python code
Design Goals
- Pragmatic over pure - Real-world utility over theoretical correctness
- Pythonic over academic - Natural Python style over functional purism
- Type-safe over dynamic - Catch errors at compile time, not runtime
- Simple over clever - Clear code over clever abstractions