Unit Monad
Represent computations with no meaningful return value
The Unit monad represents computations that produce a value but can also represent the unit type (void), similar to Python's None or other languages' unit type. It's useful for sequencing operations where the return value is not meaningful.
Unit[A] wraps a value of type A or None, providing a way to represent void operations in a functional style.
Creating Units
Creating Empty Units
The Unit constructor creates an empty Unit value.
from better_py import Unit
unit = Unit()
repr(unit) # "Unit()"Use this for operations that don't produce meaningful values.
Wrapping Values
The Unit.of method creates a Unit from a value.
from better_py import Unit
unit = Unit.of(42)
repr(unit) # "Unit(42)"Use this when you need to wrap a value in a Unit context.
Creating Unit Type
The Unit.unit method creates an empty Unit value.
from better_py import Unit
unit = Unit.unit()
repr(unit) # "Unit()"This is a named way to create an empty Unit for clarity in your code.
Transforming Units
Mapping Values
The map method applies a function to the Unit value.
from better_py import Unit
Unit.of(5).map(lambda x: x * 2) # Unit(10)
Unit().map(lambda x: x * 2) # Unit()When map is called on an empty Unit, it returns the Unit unchanged.
Real-World Pattern: Multi-Step Pipeline
from better_py import Unit
def validate(data: dict) -> Unit[dict]:
if not data.get("name"):
raise ValueError("Name required")
return Unit.of(data)
def transform(data: dict) -> Unit[dict]:
return Unit.of({**data, "processed": True})
def persist(data: dict) -> Unit[None]:
db.save(data)
return Unit.unit()
def process_data(data: dict) -> Unit[None]:
return (Unit.of(data)
.map(lambda d: validate(d))
.map(lambda d: transform(d))
.map(lambda d: persist(d))
.map(lambda _: Unit.unit()))
process_data({"name": "Alice"})This pattern shows Unit's strength for sequencing operations: each step transforms or processes data, and the final Unit.unit() represents the completion of the pipeline without a meaningful return value.
When to Use
Use Unit when:
- You have operations with no meaningful return value
- You want to sequence side effects
- You're building pipelines with void operations
- You want to represent void/unit type
- You need functional style for void operations
Don't use Unit when:
- You have meaningful return values (use plain types)
- You need optional values (use
Maybeinstead) - You need error handling (use
Resultinstead) - You need side effect management (use
IOinstead)