|
1 | | -from typing import Callable, Tuple, TypeVar |
| 1 | +from itertools import chain, tee, zip_longest |
| 2 | +from typing import Callable, Iterable, Tuple, TypeGuard, TypeVar |
2 | 3 |
|
3 | 4 | _T_contra = TypeVar("_T_contra", contravariant=True) |
4 | 5 | _T2_contra = TypeVar("_T2_contra", contravariant=True) |
5 | 6 | _T3_contra = TypeVar("_T3_contra", contravariant=True) |
6 | 7 | _T_co = TypeVar("_T_co", covariant=True) |
| 8 | +_T2_co = TypeVar("_T2_co", covariant=True) |
7 | 9 | _T_inv = TypeVar("_T_inv") |
| 10 | +_T2_inv = TypeVar("_T2_inv") |
8 | 11 |
|
9 | 12 |
|
10 | 13 | def compose( |
@@ -201,3 +204,123 @@ def pipe2( |
201 | 204 | True |
202 | 205 | """ |
203 | 206 | return expand2(pipe(compact2(f), g)) |
| 207 | + |
| 208 | + |
| 209 | +def arrow( |
| 210 | + func1: Callable[[_T_contra], _T_co], |
| 211 | + func2: Callable[[_T2_contra], _T2_co], |
| 212 | + inp: Tuple[_T_contra, _T2_contra], |
| 213 | +) -> Tuple[_T_co, _T2_co]: |
| 214 | + """applies different functions for elements of the tuple like Control.Arrow ***""" |
| 215 | + |
| 216 | + return (func1(inp[0]), func2(inp[1])) |
| 217 | + |
| 218 | + |
| 219 | +def partial_1_1( |
| 220 | + f: Callable[[_T_contra, _T2_contra], _T_co], p1: _T_contra |
| 221 | +) -> Callable[[_T2_contra], _T_co]: |
| 222 | + """ |
| 223 | + partial application of one parameter. Safe for static type-checking |
| 224 | +
|
| 225 | + Equiv: functools.partial |
| 226 | + """ |
| 227 | + |
| 228 | + def inter_(value: _T2_contra) -> _T_co: |
| 229 | + return f(p1, value) |
| 230 | + |
| 231 | + return inter_ |
| 232 | + |
| 233 | + |
| 234 | +def partial_2_1( |
| 235 | + f: Callable[[_T_contra, _T2_contra, _T3_contra], _T_co], p1: _T_contra, p2: _T2_contra |
| 236 | +) -> Callable[[_T3_contra], _T_co]: |
| 237 | + """ |
| 238 | + partial application of one parameter. Safe for static type-checking |
| 239 | +
|
| 240 | + Equiv: functools.partial |
| 241 | + """ |
| 242 | + |
| 243 | + def inter_(value: _T3_contra) -> _T_co: |
| 244 | + return f(p1, p2, value) |
| 245 | + |
| 246 | + return inter_ |
| 247 | + |
| 248 | + |
| 249 | +def filter_(f: Callable[[_T_contra], bool], p1: Iterable[_T_contra]) -> Iterable[_T_contra]: |
| 250 | + """ |
| 251 | + typed filter |
| 252 | +
|
| 253 | + Equiv: functools.filter |
| 254 | + """ |
| 255 | + |
| 256 | + return filter(f, p1) |
| 257 | + |
| 258 | + |
| 259 | +def filter_guarded( |
| 260 | + f: Callable[[_T_contra], TypeGuard[_T2_contra]], p1: Iterable[_T_contra] |
| 261 | +) -> Iterable[_T2_contra]: |
| 262 | + """ |
| 263 | + typed filter for guarded output |
| 264 | +
|
| 265 | + Equiv: functools.filter |
| 266 | + """ |
| 267 | + |
| 268 | + return filter(f, p1) |
| 269 | + |
| 270 | + |
| 271 | +def map_(f: Callable[[_T_contra], _T_co], p1: Iterable[_T_contra]) -> Iterable[_T_co]: |
| 272 | + """ |
| 273 | + typed map |
| 274 | +
|
| 275 | + Equiv: functools.map |
| 276 | + """ |
| 277 | + |
| 278 | + return map(f, p1) |
| 279 | + |
| 280 | + |
| 281 | +def tee_(inp: Iterable[_T_contra]) -> Tuple[Iterable[_T_contra], Iterable[_T_contra]]: |
| 282 | + """ |
| 283 | + duplicate iterable |
| 284 | + >>> inp = [1, 2, 3] |
| 285 | + >>> a, b = tee_(inp) |
| 286 | + >>> list(a) |
| 287 | + [1, 2, 3] |
| 288 | + >>> list(b) |
| 289 | + [1, 2, 3] |
| 290 | + """ |
| 291 | + result = tee(inp) |
| 292 | + return result[0], result[1] |
| 293 | + |
| 294 | + |
| 295 | +def zip_longest_( |
| 296 | + inp: Tuple[Iterable[_T_inv], Iterable[_T2_inv]], |
| 297 | +) -> Iterable[Tuple[_T_inv | None, _T2_inv | None]]: |
| 298 | + """ |
| 299 | + zip tuple of iterables into iterable of tuples |
| 300 | + >>> inp = ([1, 2], [4, 5, 6]) |
| 301 | + >>> list(zip_longest_(inp)) |
| 302 | + [(1, 4), (2, 5), (None, 6)] |
| 303 | + """ |
| 304 | + return zip_longest(inp[0], inp[1]) |
| 305 | + |
| 306 | + |
| 307 | +def unzip( |
| 308 | + inp: Iterable[Tuple[_T_inv, _T2_inv]], |
| 309 | +) -> Tuple[Iterable[_T_inv], Iterable[_T2_inv]]: |
| 310 | + """ |
| 311 | + unzip iterable of tuples |
| 312 | + >>> a, b = unzip([(1, 2), (3, 4), (5, 6)]) |
| 313 | + >>> list(a) |
| 314 | + [1, 3, 5] |
| 315 | + >>> list(b) |
| 316 | + [2, 4, 6] |
| 317 | + """ |
| 318 | + fst_i: Callable[[Iterable[Tuple[_T_inv, _T2_inv]]], Iterable[_T_inv]] = partial_1_1(map_, fst) |
| 319 | + snd_i: Callable[[Iterable[Tuple[_T_inv, _T2_inv]]], Iterable[_T2_inv]] = partial_1_1(map_, snd) |
| 320 | + split = partial_2_1(arrow, fst_i, snd_i) |
| 321 | + func = compose(split, tee_) |
| 322 | + return func(inp) |
| 323 | + |
| 324 | + |
| 325 | +def chain_from_iterable(inp: Iterable[Iterable[_T_inv]]) -> Iterable[_T_inv]: |
| 326 | + return chain.from_iterable(inp) |
0 commit comments