Skip to content

trcks.fp.monads.tuple_

Monadic functions for homogeneous tuples.

Provides utilities for functional composition of functions returning homogeneous tuple values.

Note

The underscore in the module name helps to avoid collisions with the built-in class tuple.

Example

Create and process a homogeneous tuple:

>>> from trcks.fp.composition import pipe
>>> from trcks.fp.monads import tuple_ as t
>>> def double_integer(n: int) -> int:
...     return n * 2
...
>>> def log_integer(n: int) -> None:
...     print(f"Received: {n}")
...
>>> tpl = pipe(
...     (
...         (1, 2, 3),
...         t.map_(double_integer),
...         t.tap(log_integer),
...     )
... )
Received: 2
Received: 4
Received: 6
>>> tpl
(2, 4, 6)

Map each element to a homogeneous tuple and flatten the result:

>>> from trcks.fp.composition import pipe
>>> from trcks.fp.monads import tuple_ as t
>>> def duplicate_integer(n: int) -> tuple[int, int]:
...     return n, n
...
>>> tpl = pipe(
...     (
...         (1, 2, 3),
...         t.map_to_iterable(duplicate_integer),
...     )
... )
>>> tpl
(1, 1, 2, 2, 3, 3)

construct(value)

Create a tuple from a single value.

Parameters:

  • value (_T) –

    A single value.

Returns:

  • tuple[_T,]

    Contains the single value.

Example
>>> from trcks.fp.monads import tuple_ as t
>>> t.construct(42)
(42,)
Source code in src/trcks/fp/monads/tuple_.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def construct(value: _T) -> tuple[_T,]:
    """Create a [tuple][] from a single value.

    Args:
        value: A single value.

    Returns:
        Contains the single value.

    Example:
        >>> from trcks.fp.monads import tuple_ as t
        >>> t.construct(42)
        (42,)
    """
    return (value,)

map_(f)

Create function that maps homogeneous tuples to homogeneous tuples of the same length.

Parameters:

  • f (Callable[[_T1], _T2]) –

    Function to apply to each element.

Returns:

  • Callable[[tuple[_T1, ...]], tuple[_T2, ...]]

    Maps homogeneous tuples to homogeneous tuples of the same length according to the given function.

Note

The underscore in the function name helps to avoid collisions with the built-in function map.

Example
>>> from collections.abc import Callable
>>> from trcks.fp.monads import tuple_ as t
>>> def double_integer(n: int) -> int:
...     return n * 2
...
>>> double_integers: Callable[
...     [tuple[int, ...]], tuple[int, ...]
... ] = t.map_(double_integer)
>>> double_integers((1, 2, 3))
(2, 4, 6)
Source code in src/trcks/fp/monads/tuple_.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def map_(f: Callable[[_T1], _T2]) -> Callable[[tuple[_T1, ...]], tuple[_T2, ...]]:
    """Create function that maps homogeneous [tuple][]s to
    homogeneous [tuple][]s of the same length.

    Args:
        f: Function to apply to each element.

    Returns:
        Maps homogeneous [tuple][]s to homogeneous [tuple][]s of the same length
            according to the given function.

    Note:
        The underscore in the function name helps to avoid collisions
            with the built-in function [map][].

    Example:
        >>> from collections.abc import Callable
        >>> from trcks.fp.monads import tuple_ as t
        >>> def double_integer(n: int) -> int:
        ...     return n * 2
        ...
        >>> double_integers: Callable[
        ...     [tuple[int, ...]], tuple[int, ...]
        ... ] = t.map_(double_integer)
        >>> double_integers((1, 2, 3))
        (2, 4, 6)
    """
    return map_to_iterable(compose2((f, construct)))

map_to_iterable(f)

Create function that maps homogeneous tuples to homogeneous tuples of varying length.

Parameters:

Returns:

  • Callable[[tuple[_T1, ...]], tuple[_T2, ...]]

    Maps homogeneous tuples to homogeneous tuples of varying length according to the given function.

Example
>>> from collections.abc import Callable
>>> from trcks.fp.monads import tuple_ as t
>>> def duplicate_integer(n: int) -> tuple[int, int]:
...     return n, n
...
>>> duplicate_integers: Callable[
...     [tuple[int, ...]], tuple[int, ...]
... ] = t.map_to_iterable(duplicate_integer)
>>> duplicate_integers((1, 2, 3))
(1, 1, 2, 2, 3, 3)
Source code in src/trcks/fp/monads/tuple_.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
def map_to_iterable(
    f: Callable[[_T1], Iterable[_T2]],
) -> Callable[[tuple[_T1, ...]], tuple[_T2, ...]]:
    """Create function that maps homogeneous [tuple][]s to
    homogeneous [tuple][]s of varying length.

    Args:
        f: Function to apply to each element.

    Returns:
        Maps homogeneous [tuple][]s to homogeneous [tuple][]s of varying length
            according to the given function.

    Example:
        >>> from collections.abc import Callable
        >>> from trcks.fp.monads import tuple_ as t
        >>> def duplicate_integer(n: int) -> tuple[int, int]:
        ...     return n, n
        ...
        >>> duplicate_integers: Callable[
        ...     [tuple[int, ...]], tuple[int, ...]
        ... ] = t.map_to_iterable(duplicate_integer)
        >>> duplicate_integers((1, 2, 3))
        (1, 1, 2, 2, 3, 3)
    """

    def mapped_f(t1s: tuple[_T1, ...]) -> tuple[_T2, ...]:
        return tuple(t2 for t1 in t1s for t2 in f(t1))

    return mapped_f

map_to_tuple(f)

Deprecated alias for trcks.fp.monads.tuple_.map_to_iterable.

Source code in src/trcks/fp/monads/tuple_.py
148
149
150
151
152
153
@deprecated("Use map_to_iterable instead")
def map_to_tuple(
    f: Callable[[_T1], tuple[_T2, ...]],
) -> Callable[[tuple[_T1, ...]], tuple[_T2, ...]]:
    """Deprecated alias for [trcks.fp.monads.tuple_.map_to_iterable][]."""
    return map_to_iterable(f)  # pragma: no cover

tap(f)

Create function that applies a side effect to each element of a homogeneous tuple.

Parameters:

  • f (Callable[[_T1], object]) –

    Side effect to apply to each element.

Returns:

  • Callable[[tuple[_T1, ...]], tuple[_T1, ...]]

    Applies the given side effect to each element of a homogeneous tuple and returns the original homogeneous tuple.

Example
>>> from collections.abc import Callable
>>> from trcks.fp.monads import tuple_ as t
>>> def log_integer(n: int) -> None:
...     print(f"Received: {n}")
...
>>> log_and_pass_integers: Callable[
...     [tuple[int, ...]], tuple[int, ...]
... ] = t.tap(log_integer)
>>> tpl = log_and_pass_integers((1, 2, 3))
Received: 1
Received: 2
Received: 3
>>> tpl
(1, 2, 3)
Source code in src/trcks/fp/monads/tuple_.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
def tap(
    f: Callable[[_T1], object],
) -> Callable[[tuple[_T1, ...]], tuple[_T1, ...]]:
    """Create function that applies a side effect to each element of a homogeneous
    [tuple][].

    Args:
        f: Side effect to apply to each element.

    Returns:
        Applies the given side effect to each element of a homogeneous [tuple][] and
            returns the original homogeneous [tuple][].

    Example:
        >>> from collections.abc import Callable
        >>> from trcks.fp.monads import tuple_ as t
        >>> def log_integer(n: int) -> None:
        ...     print(f"Received: {n}")
        ...
        >>> log_and_pass_integers: Callable[
        ...     [tuple[int, ...]], tuple[int, ...]
        ... ] = t.tap(log_integer)
        >>> tpl = log_and_pass_integers((1, 2, 3))
        Received: 1
        Received: 2
        Received: 3
        >>> tpl
        (1, 2, 3)
    """
    return map_(i.tap(f))

tap_to_iterable(f)

Create function that applies a side effect with return type collections.abc.Iterable to each element of a homogeneous tuple.

Parameters:

Returns:

  • Callable[[tuple[_T1, ...]], tuple[_T1, ...]]

    Applies the given side effect to each element of a homogeneous tuple. Returns each element as many times as the side effect returns elements.

Example
>>> from collections.abc import Callable
>>> from trcks.fp.monads import tuple_ as t
>>> def get_divisors(n: int) -> tuple[int, ...]:
...     candidates = range(1, n + 1)
...     return tuple(c for c in candidates if n % c == 0)
...
>>> repeat_integers_according_to_number_of_divisors: Callable[
...     [tuple[int, ...]], tuple[int, ...]
... ] = t.tap_to_iterable(get_divisors)
>>> repeat_integers_according_to_number_of_divisors((1, 2, 3, 4))
(1, 2, 2, 3, 3, 4, 4, 4)
Source code in src/trcks/fp/monads/tuple_.py
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
def tap_to_iterable(
    f: Callable[[_T1], Iterable[object]],
) -> Callable[[tuple[_T1, ...]], tuple[_T1, ...]]:
    """Create function that applies a side effect
    with return type [collections.abc.Iterable][]
    to each element of a homogeneous [tuple][].

    Args:
        f: Side effect to apply to each element.

    Returns:
        Applies the given side effect to each element of a homogeneous [tuple][].
            Returns each element as many times as the side effect returns elements.

    Example:
        >>> from collections.abc import Callable
        >>> from trcks.fp.monads import tuple_ as t
        >>> def get_divisors(n: int) -> tuple[int, ...]:
        ...     candidates = range(1, n + 1)
        ...     return tuple(c for c in candidates if n % c == 0)
        ...
        >>> repeat_integers_according_to_number_of_divisors: Callable[
        ...     [tuple[int, ...]], tuple[int, ...]
        ... ] = t.tap_to_iterable(get_divisors)
        >>> repeat_integers_according_to_number_of_divisors((1, 2, 3, 4))
        (1, 2, 2, 3, 3, 4, 4, 4)
    """

    def bypassed_f(t1: _T1) -> tuple[_T1, ...]:
        return tuple(t1 for _t2 in f(t1))

    return map_to_iterable(bypassed_f)

tap_to_tuple(f)

Deprecated alias for trcks.fp.monads.tuple_.tap_to_iterable.

Source code in src/trcks/fp/monads/tuple_.py
222
223
224
225
226
227
@deprecated("Use tap_to_iterable instead")
def tap_to_tuple(
    f: Callable[[_T1], tuple[object, ...]],
) -> Callable[[tuple[_T1, ...]], tuple[_T1, ...]]:
    """Deprecated alias for [trcks.fp.monads.tuple_.tap_to_iterable][]."""
    return tap_to_iterable(f)  # pragma: no cover