0
# Functional Utilities
1
2
Core functional programming utilities for composition, transformation, and pipeline construction that enable declarative programming patterns and function composition.
3
4
## Capabilities
5
6
### Basic Functions
7
8
Essential utility functions that form the foundation of functional programming patterns.
9
10
```python { .api }
11
def identity(instance: T) -> T:
12
"""Returns its argument unchanged"""
13
14
def compose(first: Callable[[T], U], second: Callable[[U], V]) -> Callable[[T], V]:
15
"""Function composition (second after first)"""
16
17
def tap(function: Callable[[T], Any]) -> Callable[[T], T]:
18
"""Apply function for side effects, return original value"""
19
20
def untap(function: Callable[[T], Any]) -> Callable[[T], None]:
21
"""Apply function for side effects, return None"""
22
23
def raise_exception(exception: Exception) -> Callable[..., NoReturn]:
24
"""Helper to raise exceptions as a function"""
25
26
def not_(function: Callable[..., bool]) -> Callable[..., bool]:
27
"""Negate boolean function results"""
28
```
29
30
Usage examples:
31
32
```python
33
from returns.functions import identity, compose, tap, not_
34
35
# Identity function
36
value = identity(42) # 42
37
38
# Function composition
39
def add_one(x: int) -> int:
40
return x + 1
41
42
def multiply_two(x: int) -> int:
43
return x * 2
44
45
composed = compose(add_one, multiply_two)
46
result = composed(5) # (5 + 1) * 2 = 12
47
48
# Tap for side effects
49
def log_value(x: int) -> None:
50
print(f"Processing: {x}")
51
52
process_with_logging = tap(log_value)
53
result = process_with_logging(42) # Prints "Processing: 42", returns 42
54
55
# Negation
56
def is_positive(x: int) -> bool:
57
return x > 0
58
59
is_negative_or_zero = not_(is_positive)
60
result = is_negative_or_zero(-5) # True
61
```
62
63
### Pipeline Operations
64
65
Functions for creating data processing pipelines that enable point-free programming style.
66
67
```python { .api }
68
def flow(instance: T, *functions: Callable) -> Any:
69
"""Compose value with sequence of functions"""
70
71
def pipe(*functions: Callable) -> Callable:
72
"""Create function pipeline"""
73
74
def managed(use: Callable[[T], Container[U]], release: Callable[[T], Any]) -> Callable[[T], Container[U]]:
75
"""Resource management pattern"""
76
77
def is_successful(container: Container[T, E]) -> bool:
78
"""Check if container represents success"""
79
```
80
81
Usage examples:
82
83
```python
84
from returns.pipeline import flow, pipe, is_successful
85
from returns.result import Success, Failure
86
87
# Flow - immediate execution
88
result = flow(
89
10,
90
lambda x: x * 2, # 20
91
lambda x: x + 5, # 25
92
lambda x: x / 2, # 12.5
93
str # "12.5"
94
)
95
96
# Pipe - create reusable pipeline
97
process_number = pipe(
98
lambda x: x * 2,
99
lambda x: x + 5,
100
lambda x: x / 2,
101
str
102
)
103
result = process_number(10) # "12.5"
104
105
# Resource management
106
def use_file(file_path: str) -> Success[str]:
107
with open(file_path, 'r') as f:
108
return Success(f.read())
109
110
def cleanup_file(file_path: str) -> None:
111
print(f"Cleaning up {file_path}")
112
113
managed_file = managed(use_file, cleanup_file)
114
result = managed_file("data.txt")
115
116
# Success checking
117
success_result = Success(42)
118
failure_result = Failure("error")
119
120
print(is_successful(success_result)) # True
121
print(is_successful(failure_result)) # False
122
```
123
124
### Currying and Partial Application
125
126
Utilities for currying functions and partial application with proper type safety.
127
128
```python { .api }
129
def partial(func: Callable, *args, **kwargs) -> Callable:
130
"""Typed partial application wrapper"""
131
132
def curry(function: Callable) -> Callable:
133
"""Decorator for currying functions"""
134
```
135
136
Usage examples:
137
138
```python
139
from returns.curry import partial, curry
140
141
# Partial application
142
def add_three_numbers(a: int, b: int, c: int) -> int:
143
return a + b + c
144
145
add_10_and = partial(add_three_numbers, 10)
146
add_10_and_5 = partial(add_10_and, 5)
147
result = add_10_and_5(3) # 18
148
149
# Currying
150
@curry
151
def multiply_three(a: int, b: int, c: int) -> int:
152
return a * b * c
153
154
# Can be called in multiple ways
155
result1 = multiply_three(2)(3)(4) # 24
156
result2 = multiply_three(2, 3)(4) # 24
157
result3 = multiply_three(2)(3, 4) # 24
158
result4 = multiply_three(2, 3, 4) # 24
159
160
# Partial application with curried function
161
double = multiply_three(2)
162
quadruple = double(2)
163
result = quadruple(5) # 20
164
```
165
166
### Container Conversion
167
168
Utilities for converting between different container types and flattening nested structures.
169
170
```python { .api }
171
def flatten(container: Container[Container[T]]) -> Container[T]:
172
"""Joins two nested containers together"""
173
174
def result_to_maybe(result_container: Result[T, E]) -> Maybe[T]:
175
"""Converts Result to Maybe"""
176
177
def maybe_to_result(maybe_container: Maybe[T], default_error: E = None) -> Result[T, E]:
178
"""Converts Maybe to Result"""
179
```
180
181
Usage examples:
182
183
```python
184
from returns.converters import flatten, result_to_maybe, maybe_to_result
185
from returns.result import Success, Failure
186
from returns.maybe import Some, Nothing
187
188
# Flatten nested containers
189
nested_success = Success(Success(42))
190
flattened = flatten(nested_success) # Success(42)
191
192
nested_maybe = Some(Some("hello"))
193
flattened_maybe = flatten(nested_maybe) # Some("hello")
194
195
# Result to Maybe conversion
196
success_result = Success(42)
197
maybe_from_success = result_to_maybe(success_result) # Some(42)
198
199
failure_result = Failure("error")
200
maybe_from_failure = result_to_maybe(failure_result) # Nothing
201
202
# Maybe to Result conversion
203
some_value = Some(42)
204
result_from_some = maybe_to_result(some_value, "default error") # Success(42)
205
206
nothing_value = Nothing
207
result_from_nothing = maybe_to_result(nothing_value, "no value") # Failure("no value")
208
```
209
210
### Method Utilities
211
212
Standalone utility methods for conditional creation and container manipulation.
213
214
```python { .api }
215
def cond(condition: bool, success_value: T, failure_value: E) -> Result[T, E]:
216
"""Conditional container creation"""
217
218
def partition(containers: Iterable[Result[T, E]]) -> tuple[list[T], list[E]]:
219
"""Partition containers by success/failure"""
220
221
def unwrap_or_failure(container: Container[T, E], failure_value: E) -> T | E:
222
"""Unwrap container or return failure value"""
223
```
224
225
Usage examples:
226
227
```python
228
from returns.methods import cond, partition, unwrap_or_failure
229
from returns.result import Success, Failure
230
231
# Conditional creation
232
def validate_age(age: int) -> Result[int, str]:
233
return cond(age >= 18, age, "Must be 18 or older")
234
235
result1 = validate_age(25) # Success(25)
236
result2 = validate_age(15) # Failure("Must be 18 or older")
237
238
# Partition results
239
results = [
240
Success(1),
241
Failure("error1"),
242
Success(2),
243
Failure("error2"),
244
Success(3)
245
]
246
247
successes, failures = partition(results)
248
# successes: [1, 2, 3]
249
# failures: ["error1", "error2"]
250
251
# Unwrap with fallback
252
success_container = Success(42)
253
value1 = unwrap_or_failure(success_container, "fallback") # 42
254
255
failure_container = Failure("error")
256
value2 = unwrap_or_failure(failure_container, "fallback") # "fallback"
257
```
258
259
## Composition Patterns
260
261
### Pipeline Style
262
263
```python
264
from returns.pipeline import flow
265
from returns.functions import compose
266
267
# Sequential processing
268
data = flow(
269
"hello world",
270
str.upper, # "HELLO WORLD"
271
lambda s: s.split(), # ["HELLO", "WORLD"]
272
len, # 2
273
lambda n: n * 10 # 20
274
)
275
276
# Reusable composed function
277
process_text = compose(
278
lambda s: s.split(),
279
len
280
)
281
```
282
283
### Point-free Style
284
285
```python
286
from returns.curry import curry
287
from returns.functions import compose
288
289
@curry
290
def add(a: int, b: int) -> int:
291
return a + b
292
293
@curry
294
def multiply(a: int, b: int) -> int:
295
return a * b
296
297
# Point-free composition
298
add_five = add(5)
299
double = multiply(2)
300
process = compose(add_five, double)
301
302
result = process(10) # (10 + 5) * 2 = 30
303
```
304
305
These functional utilities provide the building blocks for creating clean, composable, and reusable code following functional programming principles while maintaining full type safety.