0
# Returns
1
2
Make your functions return something meaningful, typed, and safe! Returns is a comprehensive functional programming library for Python that enables developers to write safer, more meaningful, and typed code through monadic patterns and railway-oriented programming. It offers primitives like Maybe, Result, IO, and Future containers for handling optional values, error cases, side effects, and asynchronous operations with full type safety enforced by mypy.
3
4
## Package Information
5
6
- **Package Name**: returns
7
- **Language**: Python
8
- **Installation**: `pip install returns`
9
10
With mypy support:
11
```bash
12
pip install returns[compatible-mypy]
13
```
14
15
## Core Imports
16
17
Basic imports:
18
```python
19
from returns.result import Result, Success, Failure
20
from returns.maybe import Maybe, Some, Nothing
21
from returns.io import IO, IOResult
22
from returns.future import Future, FutureResult
23
```
24
25
Common utilities:
26
```python
27
from returns.functions import identity, compose
28
from returns.pipeline import flow, pipe
29
from returns.pointfree import bind, map_
30
```
31
32
## Basic Usage
33
34
```python
35
from returns.result import Success, Failure, safe
36
from returns.maybe import Some, Nothing, maybe
37
from returns.pipeline import flow
38
39
# Result type for operations that can fail
40
@safe
41
def divide(a: int, b: int) -> float:
42
return a / b
43
44
result = divide(10, 2) # Success(5.0)
45
result = divide(10, 0) # Failure(ZeroDivisionError(...))
46
47
# Maybe type for handling None values
48
@maybe
49
def find_user(user_id: int) -> dict | None:
50
return {"id": user_id, "name": "John"} if user_id > 0 else None
51
52
user = find_user(1) # Some({"id": 1, "name": "John"})
53
user = find_user(-1) # Nothing
54
55
# Functional composition with pipeline
56
result = flow(
57
10,
58
lambda x: x * 2, # 20
59
lambda x: x + 5, # 25
60
lambda x: Success(x) # Success(25)
61
)
62
63
# Chaining operations with bind
64
from returns.pointfree import bind
65
66
def double(x: int) -> Success[int]:
67
return Success(x * 2)
68
69
def add_five(x: int) -> Success[int]:
70
return Success(x + 5)
71
72
result = Success(10).bind(double).bind(add_five) # Success(25)
73
```
74
75
## Architecture
76
77
Returns follows functional programming principles with a focus on:
78
79
- **Monadic Containers**: Type-safe containers (Result, Maybe, IO, Future) that encapsulate values and provide composable operations
80
- **Railway-Oriented Programming**: Chain operations that can succeed or fail without explicit error handling at each step
81
- **Higher-Kinded Types**: Emulated generic type system enabling powerful abstractions while maintaining type safety
82
- **Lawful Interfaces**: Mathematical properties ensuring predictable behavior and enabling reasoning about code
83
- **Immutability**: All containers are immutable, preventing side effects and enabling safe concurrent programming
84
85
## Capabilities
86
87
### Core Container Types
88
89
Essential monadic containers for type-safe error handling, optional values, side effects, and async operations. These form the foundation of functional programming patterns in Python.
90
91
```python { .api }
92
class Result[T, E]:
93
"""Container for operations that can succeed or fail"""
94
def bind(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]: ...
95
def map(self, func: Callable[[T], U]) -> Result[U, E]: ...
96
97
class Maybe[T]:
98
"""Container for optional values"""
99
def bind(self, func: Callable[[T], Maybe[U]]) -> Maybe[U]: ...
100
def map(self, func: Callable[[T], U]) -> Maybe[U]: ...
101
102
class IO[T]:
103
"""Container for impure operations"""
104
def bind(self, func: Callable[[T], IO[U]]) -> IO[U]: ...
105
def map(self, func: Callable[[T], U]) -> IO[U]: ...
106
107
class Future[T]:
108
"""Container for async operations"""
109
async def bind(self, func: Callable[[T], Future[U]]) -> Future[U]: ...
110
async def map(self, func: Callable[[T], U]) -> Future[U]: ...
111
```
112
113
[Core Containers](./core-containers.md)
114
115
### Context and Dependencies
116
117
Context-dependent computations using the Reader monad pattern for dependency injection and environment passing without explicit parameter threading.
118
119
```python { .api }
120
class RequiresContext[T, Deps]:
121
"""Reader monad for dependency injection"""
122
def __call__(self, deps: Deps) -> T: ...
123
def bind(self, func: Callable[[T], RequiresContext[U, Deps]]) -> RequiresContext[U, Deps]: ...
124
125
class RequiresContextResult[T, E, Deps]:
126
"""Reader + Result combination"""
127
def __call__(self, deps: Deps) -> Result[T, E]: ...
128
```
129
130
[Context Operations](./context-operations.md)
131
132
### Functional Utilities
133
134
Core functional programming utilities for composition, transformation, and pipeline construction that enable declarative programming patterns.
135
136
```python { .api }
137
def identity(value: T) -> T: ...
138
def compose(first: Callable[[T], U], second: Callable[[U], V]) -> Callable[[T], V]: ...
139
def flow(instance: T, *functions: Callable) -> Any: ...
140
def pipe(*functions: Callable) -> Callable: ...
141
```
142
143
[Functional Utilities](./functional-utilities.md)
144
145
### Point-free Operations
146
147
Point-free style functions that enable composition without explicitly naming intermediate values, supporting functional programming idioms.
148
149
```python { .api }
150
def bind(func: Callable[[T], Container[U]]) -> Callable[[Container[T]], Container[U]]: ...
151
def map_(func: Callable[[T], U]) -> Callable[[Container[T]], Container[U]]: ...
152
def alt(func: Callable[[E], F]) -> Callable[[Container[T, E]], Container[T, F]]: ...
153
```
154
155
[Point-free Operations](./pointfree.md)
156
157
### Async and Concurrency
158
159
Containers and utilities for handling asynchronous operations with type safety and composable error handling in concurrent environments.
160
161
```python { .api }
162
class Future[T]:
163
"""Async container for operations that don't fail"""
164
async def awaitable(self) -> T: ...
165
166
class FutureResult[T, E]:
167
"""Async container for operations that can fail"""
168
async def awaitable(self) -> Result[T, E]: ...
169
```
170
171
[Async Operations](./async-operations.md)
172
173
### Iteration and Collection
174
175
Utilities for working with iterables of containers, providing declarative approaches to collection processing with type-safe error propagation.
176
177
```python { .api }
178
class Fold:
179
"""Declarative iterable processing"""
180
@staticmethod
181
def loop(iterable: Iterable[Container[T]], acc: Container[U], func: Callable) -> Container[U]: ...
182
@staticmethod
183
def collect(iterable: Iterable[Container[T]], acc: Container[List[T]]) -> Container[List[T]]: ...
184
```
185
186
[Iteration Utilities](./iteration-utilities.md)
187
188
### Conversion and Interop
189
190
Utilities for converting between different container types and integrating with external libraries and legacy code.
191
192
```python { .api }
193
def result_to_maybe(result: Result[T, E]) -> Maybe[T]: ...
194
def maybe_to_result(maybe: Maybe[T], default_error: E = None) -> Result[T, E]: ...
195
def flatten(container: Container[Container[T]]) -> Container[T]: ...
196
```
197
198
[Conversions](./conversions.md)
199
200
### Testing and Development
201
202
Integration tools for testing frameworks (pytest, hypothesis), static analysis (mypy), and development workflows with functional containers.
203
204
```python { .api }
205
# Pytest integration
206
from returns.contrib.pytest import ReturnsAsserts
207
208
# Hypothesis strategies
209
from returns.contrib.hypothesis import get_strategies
210
```
211
212
[Development Tools](./development-tools.md)
213
214
### Container Utilities
215
216
Common utility functions for container manipulation, conditional creation, and state checking that simplify working with container collections.
217
218
```python { .api }
219
def cond(condition: bool, success_value: T, failure_value: E) -> Result[T, E]: ...
220
def partition(containers: Iterable[Result[T, E]]) -> tuple[list[T], list[E]]: ...
221
def unwrap_or_failure(container: Result[T, E], default_failure: F) -> T | F: ...
222
```
223
224
[Container Methods](./container-methods.md)
225
226
### Tail-Call Optimization
227
228
Utilities for converting recursive functions into iterative ones to avoid stack overflow errors, enabling safe recursion in Python.
229
230
```python { .api }
231
class Trampoline[T]:
232
"""Container for tail-call optimized recursion"""
233
def run(self) -> T: ...
234
def bind(self, func: Callable[[T], Trampoline[U]]) -> Trampoline[U]: ...
235
236
def trampoline(func: Callable[..., Trampoline[T]]) -> Callable[..., T]: ...
237
```
238
239
[Trampolines](./trampolines.md)
240
241
### Unsafe Operations
242
243
Escape hatch utilities for breaking out of the functional programming world when interfacing with legacy code or at application boundaries.
244
245
```python { .api }
246
def unsafe_perform_io(container: IO[T]) -> T:
247
"""Execute IO container and extract value (unsafe!)"""
248
```
249
250
[Unsafe Operations](./unsafe-operations.md)
251
252
## Type Definitions
253
254
Core type definitions used across the library:
255
256
```python { .api }
257
from typing import TypeVar, Generic, Callable, Awaitable
258
259
T = TypeVar('T') # Success type
260
E = TypeVar('E') # Error type
261
U = TypeVar('U') # Mapped type
262
Deps = TypeVar('Deps') # Dependencies type
263
264
# Common type aliases
265
ResultE[T] = Result[T, Exception]
266
IOResultE[T] = IOResult[T, Exception]
267
FutureResultE[T] = FutureResult[T, Exception]
268
NoDeps = Any # No dependencies marker
269
```