Skip to content

Commit 06e6f15

Browse files
authored
Make Option covariant (#190)
* Make Option covariant * Use a separate covariant out type * Fixed Result covariance
1 parent 65cd3a9 commit 06e6f15

File tree

8 files changed

+285
-238
lines changed

8 files changed

+285
-238
lines changed

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
> Pragmatic functional programming
1010
1111
Expression aims to be a solid, type-safe, pragmatic, and high performance
12-
library for frictionless and practical functional programming in Python 3.11+.
12+
library for frictionless and practical functional programming in Python 3.10+.
1313

1414
By pragmatic, we mean that the goal of the library is to use simple abstractions
1515
to enable you to do practical and productive functional programming in Python
@@ -57,7 +57,7 @@ similar to Python, but F# can also do a lot of things better than Python:
5757
## Getting Started
5858

5959
You can install the latest `expression` from PyPI by running `pip` (or
60-
`pip3`). Note that `expression` only works for Python 3.11+.
60+
`pip3`). Note that `expression` only works for Python 3.10+.
6161

6262
```console
6363
> pip install expression
@@ -88,7 +88,7 @@ To add Pydantic v2 support, install the `pydantic` extra:
8888
functions and methods.
8989
- Support PEP 634 and structural pattern matching.
9090
- Code must pass strict static type checking by
91-
[pylance](https://devblogs.microsoft.com/python/announcing-pylance-fast-feature-rich-language-support-for-python-in-visual-studio-code/).
91+
[Pylance](https://devblogs.microsoft.com/python/announcing-pylance-fast-feature-rich-language-support-for-python-in-visual-studio-code/).
9292
Pylance is awesome, use it!
9393
- [Pydantic](https://pydantic-docs.helpmanual.io/) friendly data types. Use Expression
9494
types as part of your Pydantic data model and (de)serialize to/from JSON.
@@ -325,7 +325,6 @@ The map2 function allows us to achieve this behavior. It takes two Option values
325325

326326
This approach ensures that our combined value reflects the presence or absence of data in the original Options.
327327

328-
329328
```python
330329
from expression import Some, Nothing, Option
331330
from operator import add

expression/core/compose.py

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
_J = TypeVar("_J")
1818

1919
_P = TypeVarTuple("_P")
20-
_Q = TypeVarTuple("_Q")
2120
_X = TypeVarTuple("_X")
2221
_Y = TypeVarTuple("_Y")
2322
_Z = TypeVarTuple("_Z")
@@ -41,70 +40,76 @@ def compose(__fn1: Callable[[_A], _B], __fn2: Callable[[_B], _C], __fn3: Callabl
4140

4241
@overload
4342
def compose(
44-
__fn1: Callable[[_A], _B],
45-
__fn2: Callable[[_B], _C],
46-
__fn3: Callable[[_C], _D],
47-
__fn4: Callable[[_D], _E],
43+
fn1: Callable[[_A], _B],
44+
fn2: Callable[[_B], _C],
45+
fn3: Callable[[_C], _D],
46+
fn4: Callable[[_D], _E],
47+
/,
4848
) -> Callable[[_A], _E]: ...
4949

5050

5151
@overload
5252
def compose(
53-
__fn1: Callable[[_A], _B],
54-
__fn2: Callable[[_B], _C],
55-
__fn3: Callable[[_C], _D],
56-
__fn4: Callable[[_D], _E],
57-
__fn5: Callable[[_E], _F],
53+
fn1: Callable[[_A], _B],
54+
fn2: Callable[[_B], _C],
55+
fn3: Callable[[_C], _D],
56+
fn4: Callable[[_D], _E],
57+
fn5: Callable[[_E], _F],
58+
/,
5859
) -> Callable[[_A], _F]: ...
5960

6061

6162
@overload
6263
def compose(
63-
__fn1: Callable[[_A], _B],
64-
__fn2: Callable[[_B], _C],
65-
__fn3: Callable[[_C], _D],
66-
__fn4: Callable[[_D], _E],
67-
__fn5: Callable[[_E], _F],
68-
__fn6: Callable[[_F], _G],
64+
fn1: Callable[[_A], _B],
65+
fn2: Callable[[_B], _C],
66+
fn3: Callable[[_C], _D],
67+
fn4: Callable[[_D], _E],
68+
fn5: Callable[[_E], _F],
69+
fn6: Callable[[_F], _G],
70+
/,
6971
) -> Callable[[_A], _G]: ...
7072

7173

7274
@overload
7375
def compose(
74-
__fn1: Callable[[_A], _B],
75-
__fn2: Callable[[_B], _C],
76-
__fn3: Callable[[_C], _D],
77-
__fn4: Callable[[_D], _E],
78-
__fn5: Callable[[_E], _F],
79-
__fn6: Callable[[_F], _G],
80-
__fn7: Callable[[_G], _H],
76+
fn1: Callable[[_A], _B],
77+
fn2: Callable[[_B], _C],
78+
fn3: Callable[[_C], _D],
79+
fn4: Callable[[_D], _E],
80+
fn5: Callable[[_E], _F],
81+
fn6: Callable[[_F], _G],
82+
fn7: Callable[[_G], _H],
83+
/,
8184
) -> Callable[[_A], _H]: ...
8285

8386

8487
@overload
8588
def compose(
86-
__fn1: Callable[[_A], _B],
87-
__fn2: Callable[[_B], _C],
88-
__fn3: Callable[[_C], _D],
89-
__fn4: Callable[[_D], _E],
90-
__fn5: Callable[[_E], _F],
91-
__fn6: Callable[[_F], _G],
92-
__fn7: Callable[[_G], _H],
93-
__fn8: Callable[[_H], _T],
89+
fn1: Callable[[_A], _B],
90+
fn2: Callable[[_B], _C],
91+
fn3: Callable[[_C], _D],
92+
fn4: Callable[[_D], _E],
93+
fn5: Callable[[_E], _F],
94+
fn6: Callable[[_F], _G],
95+
fn7: Callable[[_G], _H],
96+
fn8: Callable[[_H], _T],
97+
/,
9498
) -> Callable[[_A], _T]: ...
9599

96100

97101
@overload
98102
def compose(
99-
__fn1: Callable[[_A], _B],
100-
__fn2: Callable[[_B], _C],
101-
__fn3: Callable[[_C], _D],
102-
__fn4: Callable[[_D], _E],
103-
__fn5: Callable[[_E], _F],
104-
__fn6: Callable[[_F], _G],
105-
__fn7: Callable[[_G], _H],
106-
__fn8: Callable[[_H], _T],
107-
__fn9: Callable[[_T], _J],
103+
fn1: Callable[[_A], _B],
104+
fn2: Callable[[_B], _C],
105+
fn3: Callable[[_C], _D],
106+
fn4: Callable[[_D], _E],
107+
fn5: Callable[[_E], _F],
108+
fn6: Callable[[_F], _G],
109+
fn7: Callable[[_G], _H],
110+
fn8: Callable[[_H], _T],
111+
fn9: Callable[[_T], _J],
112+
/,
108113
) -> Callable[[_A], _J]: ...
109114

110115

@@ -141,29 +146,31 @@ def starcompose() -> Callable[[Any], Any]: ...
141146

142147

143148
@overload
144-
def starcompose(__fn1: Callable[[Unpack[_P]], _A]) -> Callable[[Unpack[_P]], _A]: ...
149+
def starcompose(fn1: Callable[[Unpack[_P]], _A], /) -> Callable[[Unpack[_P]], _A]: ...
145150

146151

147152
@overload
148153
def starcompose(
149-
__fn1: Callable[[Unpack[_P]], tuple[Unpack[_Y]]], __fn2: Callable[[Unpack[_Y]], _B]
154+
fn1: Callable[[Unpack[_P]], tuple[Unpack[_Y]]], fn2: Callable[[Unpack[_Y]], _B], /
150155
) -> Callable[[Unpack[_P]], _B]: ...
151156

152157

153158
@overload
154159
def starcompose(
155-
__fn1: Callable[[Unpack[_P]], tuple[Unpack[_Y]]],
156-
__fn2: Callable[[Unpack[_Y]], tuple[Unpack[_Z]]],
157-
__fn3: Callable[[Unpack[_Z]], _C],
160+
fn1: Callable[[Unpack[_P]], tuple[Unpack[_Y]]],
161+
fn2: Callable[[Unpack[_Y]], tuple[Unpack[_Z]]],
162+
fn3: Callable[[Unpack[_Z]], _C],
163+
/,
158164
) -> Callable[[Unpack[_P]], _C]: ...
159165

160166

161167
@overload
162168
def starcompose(
163-
__fn1: Callable[[Unpack[_P]], tuple[Unpack[_Y]]],
164-
__fn2: Callable[[Unpack[_Y]], tuple[Unpack[_Z]]],
165-
__fn3: Callable[[Unpack[_Z]], tuple[Unpack[_X]]],
166-
__fn4: Callable[[Unpack[_X]], _D],
169+
fn1: Callable[[Unpack[_P]], tuple[Unpack[_Y]]],
170+
fn2: Callable[[Unpack[_Y]], tuple[Unpack[_Z]]],
171+
fn3: Callable[[Unpack[_Z]], tuple[Unpack[_X]]],
172+
fn4: Callable[[Unpack[_X]], _D],
173+
/,
167174
) -> Callable[[Unpack[_P]], _D]: ...
168175

169176

0 commit comments

Comments
 (0)