pythonic-fp-fptools 5.1.1__tar.gz → 5.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/CHANGELOG.rst +70 -58
  2. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/PKG-INFO +15 -12
  3. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/README.rst +5 -4
  4. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/pyproject.toml +10 -8
  5. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/either.py +25 -17
  6. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/either.pyi +1 -1
  7. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/function.py +22 -26
  8. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/function.pyi +2 -1
  9. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/lazy.py +18 -22
  10. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/maybe.py +7 -8
  11. pythonic_fp_fptools-5.2.0/src/pythonic_fp/fptools/py.typed +0 -0
  12. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/state.py +7 -8
  13. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/either/test_sequence_either.py +1 -1
  14. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/maybe/test_sequence_maybe.py +1 -1
  15. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/.gitignore +0 -0
  16. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/LICENSE +0 -0
  17. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/__init__.py +0 -0
  18. /pythonic_fp_fptools-5.1.1/src/pythonic_fp/fptools/py.typed → /pythonic_fp_fptools-5.2.0/src/pythonic_fp/fptools/__init__.pyi +0 -0
  19. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/lazy.pyi +0 -0
  20. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/maybe.pyi +0 -0
  21. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/src/pythonic_fp/fptools/state.pyi +0 -0
  22. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/either/test_either.py +0 -0
  23. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/either/test_str_repr_either.py +0 -0
  24. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/function/test_function.py +0 -0
  25. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/lazy/test_lazy.py +0 -0
  26. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/maybe/maybe.py +0 -0
  27. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/maybe/test_str_repr_maybe.py +0 -0
  28. {pythonic_fp_fptools-5.1.1 → pythonic_fp_fptools-5.2.0}/tests/state/test_state.py +0 -0
@@ -17,22 +17,38 @@ See `Semantic Versioning 2.0.0 <https://semver.org>`_.
17
17
  Releases and Important Milestones
18
18
  ---------------------------------
19
19
 
20
- 5.1.0 - 2025-09-09
21
- ~~~~~~~~~~~~~~~~~~
20
+ PyPI 5.2.0 - 2026-01-13
21
+ ~~~~~~~~~~~~~~~~~~~~~~~
22
+
23
+ Added function.compose back on 2025-12-04. Docstring updates for Sphinx.
24
+
25
+ PyPI 5.1.2 - 2025-09-28
26
+ ~~~~~~~~~~~~~~~~~~~~~~~
27
+
28
+ Patch bump for pythonic-fp PyPI coordinated release 3.3.3.
29
+
30
+ PyPI 5.1.1 - 2025-09-09
31
+ ~~~~~~~~~~~~~~~~~~~~~~~
32
+
33
+ Spotted a dependency issue when pip installing repo.
34
+
35
+
36
+ PyPI 5.1.0 - 2025-09-09
37
+ ~~~~~~~~~~~~~~~~~~~~~~~
22
38
 
23
39
  Updated docstrings for new Sphinx docs structure. Probably just a PATCH release,
24
40
  made it a MINOR release due to introducing .pyi files.
25
41
 
26
42
 
27
- 5.0.0 - 2025-08-02
28
- ~~~~~~~~~~~~~~~~~~
43
+ PyPI 5.0.0 - 2025-08-02
44
+ ~~~~~~~~~~~~~~~~~~~~~~~
29
45
 
30
46
  Coordinated entire project pythonic-fp PyPI deployment.
31
47
 
32
48
  - moved maybe.py and xor.py from containers, renamed xor.py -> either.py.
33
49
 
34
- 4.0.0 - 2025-07-13
35
- ~~~~~~~~~~~~~~~~~~
50
+ PyPI 4.0.0 - 2025-07-13
51
+ ~~~~~~~~~~~~~~~~~~~~~~~
36
52
 
37
53
  Dropped developer status to Beta
38
54
 
@@ -42,15 +58,15 @@ Dropped developer status to Beta
42
58
  TODO: After next Boring Math (bm) deployment, I should be able to archive
43
59
  my dtools namespace repos
44
60
 
45
- 3.0.0 - 2025-07-06
46
- ~~~~~~~~~~~~~~~~~~
61
+ PyPI 3.0.0 - 2025-07-06
62
+ ~~~~~~~~~~~~~~~~~~~~~~~
47
63
 
48
64
  First PyPI release as ``pythonic-fp.fptools``
49
65
 
50
66
  - dropping dtools namespace name because there is a repo by that name.
51
67
 
52
- 2.0.0 - 2025-05-22
53
- ~~~~~~~~~~~~~~~~~~
68
+ PyPI 2.0.0 - 2025-05-22
69
+ ~~~~~~~~~~~~~~~~~~~~~~~
54
70
 
55
71
  - Moved dtools.fp.err_handling to the dtools.containers PyPI project
56
72
 
@@ -60,8 +76,8 @@ First PyPI release as ``pythonic-fp.fptools``
60
76
 
61
77
  - will import dtools.fp.lazy directly for this functionality
62
78
 
63
- 1.7.0 - 2025-04-22
64
- ~~~~~~~~~~~~~~~~~~
79
+ PyPI 1.7.0 - 2025-04-22
80
+ ~~~~~~~~~~~~~~~~~~~~~~~
65
81
 
66
82
  Last PyPI release as dtools.fp
67
83
 
@@ -70,8 +86,8 @@ Last PyPI release as dtools.fp
70
86
  - docstring changes
71
87
  - pyproject.toml standardization
72
88
 
73
- 1.6.1.0 - 2025-04-17
74
- ~~~~~~~~~~~~~~~~~~~~
89
+ PyPI 1.6.1.0 - 2025-04-17
90
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
75
91
 
76
92
  - MB.sequence and XOR.sequence now return a wrapped iterator
77
93
 
@@ -85,13 +101,13 @@ Last PyPI release as dtools.fp
85
101
 
86
102
  - Also noticed MB and XOR still have camelCase APIs
87
103
 
88
- 1.6.0 - 2025-04-07
89
- ~~~~~~~~~~~~~~~~~~
104
+ PyPI 1.6.0 - 2025-04-07
105
+ ~~~~~~~~~~~~~~~~~~~~~~~
90
106
 
91
107
  - typing improvements
92
108
 
93
- 1.4.0 - 2025-03-16
94
- ~~~~~~~~~~~~~~~~~~
109
+ PyPI 1.4.0 - 2025-03-16
110
+ ~~~~~~~~~~~~~~~~~~~~~~~
95
111
 
96
112
  - added two state changing methods to dtools.err_handling.MB
97
113
 
@@ -109,13 +125,13 @@ Last PyPI release as dtools.fp
109
125
 
110
126
  - avoid using these methods in pure code
111
127
 
112
- 1.3.1 - 2025-02-05
113
- ~~~~~~~~~~~~~~~~~~
128
+ PyPI 1.3.1 - 2025-02-05
129
+ ~~~~~~~~~~~~~~~~~~~~~~~
114
130
 
115
131
  - added class method sequence to class State
116
132
 
117
- 1.3.0 - 2025-01-17
118
- ~~~~~~~~~~~~~~~~~~
133
+ PyPI 1.3.0 - 2025-01-17
134
+ ~~~~~~~~~~~~~~~~~~~~~~~
119
135
 
120
136
  First release as dtools.fp
121
137
 
@@ -124,25 +140,23 @@ Repo name changes.
124
140
  - GitHub: fp -> dtools-fp
125
141
  - PyPI: grscheller.fp -> dtools.fp
126
142
 
127
- 1.2.0 - 2025-01-04
128
- ~~~~~~~~~~~~~~~~~~
143
+ PyPI 1.2.0 - 2025-01-04
144
+ ~~~~~~~~~~~~~~~~~~~~~~~
129
145
 
130
146
  - added modules lazy and state
131
147
  - renamed flatmap methods to bind
132
148
  - minor MB and XOR updates/corrections
133
149
 
134
- 1.1.0 - 2024-11-18
135
- ~~~~~~~~~~~~~~~~~~
150
+ PyPI 1.1.0 - 2024-11-18
151
+ ~~~~~~~~~~~~~~~~~~~~~~~
136
152
 
137
153
  Added fp.function module.
138
154
 
139
155
  - combine and partially apply functions as first class objects
140
156
  - some tests may be lacking
141
157
 
142
- 1.0.2.0 - 2024-10-20
143
- ~~~~~~~~~~~~~~~~~~~~
144
-
145
- Development environment only.
158
+ Version 1.0.2.0 - 2024-10-20 (Devel environment only)
159
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146
160
 
147
161
  - breaking API changes, next PyPI release will be 1.1.0.
148
162
  - renamed module ``nothingness`` to ``singletons``
@@ -158,16 +172,16 @@ Development environment only.
158
172
 
159
173
  - will redo docs in docs repo
160
174
 
161
- 1.0.1 - 2024-10-20
162
- ~~~~~~~~~~~~~~~~~~
175
+ PyPI 1.0.1 - 2024-10-20
176
+ ~~~~~~~~~~~~~~~~~~~~~~~
163
177
 
164
178
  - removed docs from repo
165
179
  - docs for all grscheller namespace projects maintained here
166
180
 
167
181
  - https://grscheller.github.io/grscheller-pypi-namespace-docs/
168
182
 
169
- 1.0.0 - 2024-10-18
170
- ~~~~~~~~~~~~~~~~~~
183
+ PyPI 1.0.0 - 2024-10-18
184
+ ~~~~~~~~~~~~~~~~~~~~~~~
171
185
 
172
186
  Decided to make this release first stable release.
173
187
 
@@ -177,33 +191,31 @@ Decided to make this release first stable release.
177
191
 
178
192
  - pytest improvements based on pytest documentation
179
193
 
180
- 0.4.0 - 2024-10-03
181
- ~~~~~~~~~~~~~~~~~~
194
+ PyPI 0.4.0 - 2024-10-03
195
+ ~~~~~~~~~~~~~~~~~~~~~~~
182
196
 
183
197
  Long overdue PyPI release.
184
198
 
185
- 0.3.5.1 - 2024-10-03
186
- ~~~~~~~~~~~~~~~~~~~~
187
-
188
- Development environment only.
199
+ Version 0.3.5.1 - 2024-10-03 (Devel environment only)
200
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189
201
 
190
- - New module ``grscheller.fp.nothingness`` for
202
+ New module ``grscheller.fp.nothingness`` which contains
191
203
 
192
- - Singleton ``noValue`` representing a missing value
204
+ - Singleton ``noValue`` representing a missing value
193
205
 
194
- - similar to ``None`` but while
206
+ - similar to ``None`` but while
195
207
 
196
- - ``None`` represent "returned no values"
197
- - ``noValue: _NoValue = _NoValue()`` represents an absent value
208
+ - ``None`` represent "returned no values"
209
+ - ``noValue: _NoValue = _NoValue()`` represents an absent value
198
210
 
199
- - mostly used as an implementation detail
211
+ - mostly used as an implementation detail
200
212
 
201
- - allows client code to use ``None`` as a sentinel value
213
+ - allows client code to use ``None`` as a sentinel value
202
214
 
203
- - prefer class ``MB`` to represent a missing value in client code
215
+ - prefer class ``MB`` to represent a missing value in client code
204
216
 
205
- 0.3.3 - 2024-08-25
206
- ~~~~~~~~~~~~~~~~~~
217
+ PyPI 0.3.3 - 2024-08-25
218
+ ~~~~~~~~~~~~~~~~~~~~~~~
207
219
 
208
220
  - removed woException ``XOR`` method
209
221
 
@@ -214,23 +226,23 @@ Development environment only.
214
226
  - makeRight(self, right: R|Nada=nada) -> XOR\[L, R\]:
215
227
  - swapRight(self, right: R) -> XOR\[L, R\]:
216
228
 
217
- 0.3.0 - 2024-08-17
218
- ~~~~~~~~~~~~~~~~~~
229
+ PyPI 0.3.0 - 2024-08-17
230
+ ~~~~~~~~~~~~~~~~~~~~~~~
219
231
 
220
232
  Class Nothing re-added but renamed class Nada.
221
233
 
222
234
  Version grscheller.untyped.nothing for more strictly typed code.
223
235
 
224
- 0.2.1 - 2024-07-26
225
- ~~~~~~~~~~~~~~~~~~
236
+ PyPI 0.2.1 - 2024-07-26
237
+ ~~~~~~~~~~~~~~~~~~~~~~~
226
238
 
227
239
  PyPI grscheller.fp package release v0.2.1
228
240
 
229
241
  - forgot to update README.md on last PyPI release
230
242
  - simplified README.md to help alleviate this mistake in the future
231
243
 
232
- 0.2.0 - 2024-07-26
233
- ~~~~~~~~~~~~~~~~~~
244
+ PyPI 0.2.0 - 2024-07-26
245
+ ~~~~~~~~~~~~~~~~~~~~~~~
234
246
 
235
247
  - from last PyPI release
236
248
 
@@ -241,8 +253,8 @@ PyPI grscheller.fp package release v0.2.1
241
253
 
242
254
  - renamed ``fp.wo_exception`` to ``fp.woException``
243
255
 
244
- 0.1.0 - 2024-07-11
245
- ~~~~~~~~~~~~~~~~~~
256
+ PyPI 0.1.0 - 2024-07-11
257
+ ~~~~~~~~~~~~~~~~~~~~~~~
246
258
 
247
259
  Initial PyPI release as grscheller.fp
248
260
 
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonic-fp-fptools
3
- Version: 5.1.1
3
+ Version: 5.2.0
4
4
  Summary: Pythonic FP - Functional Programming Tools
5
5
  Keywords: either,fp,functional,functional programming,lazy,maybe,monad,non-strict
6
6
  Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
7
7
  Requires-Python: >=3.12
8
8
  Description-Content-Type: text/x-rst
9
- Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Development Status :: 4 - Beta
10
10
  Classifier: Framework :: Pytest
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: License :: OSI Approved :: Apache Software License
@@ -14,14 +14,16 @@ Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Classifier: Typing :: Typed
16
16
  License-File: LICENSE
17
- Requires-Dist: pythonic-fp-booleans>=1.1.1
18
- Requires-Dist: pythonic-fp-circulararray>=5.3.2
19
- Requires-Dist: pythonic-fp-sentinels>=2.1.0
17
+ Requires-Dist: pythonic-fp-booleans>=2.1.1
18
+ Requires-Dist: pythonic-fp-circulararray>=6.0.1
19
+ Requires-Dist: pythonic-fp-gadgets>=4.0.2
20
20
  Requires-Dist: pytest>=8.4.1 ; extra == "test"
21
- Requires-Dist: pythonic-fp-containers>=3.0.0 ; extra == "test"
21
+ Requires-Dist: pythonic-fp-containers>=4.0.1 ; extra == "test"
22
+ Requires-Dist: pythonic-fp-iterables>=5.1.3 ; extra == "test"
23
+ Requires-Dist: pythonic-fp-queues>=5.1.1 ; extra == "test"
22
24
  Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-fptools/blob/main/CHANGELOG.rst
23
- Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/fptools/development/build/html/releases.html
24
- Project-URL: Homepage, https://github.com/grscheller/pythonic-fp/blob/main/README.md
25
+ Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/fptools/development/build/html/
26
+ Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/homepage/build/html/
25
27
  Project-URL: Source, https://github.com/grscheller/pythonic-fp-fptools
26
28
  Provides-Extra: test
27
29
 
@@ -49,16 +51,17 @@ endeavoring to be Pythonic.
49
51
 
50
52
  - the monad encapsulates a state transformation, not a "state"
51
53
 
52
- This PyPI project is part of the
53
- `pythonic-fp namespace projects
54
- <https://github.com/grscheller/pythonic-fp/blob/main/README.md>`_
54
+ Part of the
55
+ `pythonic-fp
56
+ <https://grscheller.github.io/pythonic-fp>`_
57
+ PyPI projects.
55
58
 
56
59
  Documentation
57
60
  -------------
58
61
 
59
62
  Documentation for this project is hosted on
60
63
  `GitHub Pages
61
- <https://grscheller.github.io/pythonic-fp/fptools/development/build/html>`_.
64
+ <https://grscheller.github.io/pythonic-fp/fptools>`_.
62
65
 
63
66
  Copyright and License
64
67
  ---------------------
@@ -22,16 +22,17 @@ endeavoring to be Pythonic.
22
22
 
23
23
  - the monad encapsulates a state transformation, not a "state"
24
24
 
25
- This PyPI project is part of the
26
- `pythonic-fp namespace projects
27
- <https://github.com/grscheller/pythonic-fp/blob/main/README.md>`_
25
+ Part of the
26
+ `pythonic-fp
27
+ <https://grscheller.github.io/pythonic-fp>`_
28
+ PyPI projects.
28
29
 
29
30
  Documentation
30
31
  -------------
31
32
 
32
33
  Documentation for this project is hosted on
33
34
  `GitHub Pages
34
- <https://grscheller.github.io/pythonic-fp/fptools/development/build/html>`_.
35
+ <https://grscheller.github.io/pythonic-fp/fptools>`_.
35
36
 
36
37
  Copyright and License
37
38
  ---------------------
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pythonic-fp-fptools"
3
- version = "5.1.1"
3
+ version = "5.2.0"
4
4
  readme = "README.rst"
5
5
  requires-python = ">=3.12"
6
6
  license = { file = "LICENSE" }
@@ -16,7 +16,7 @@ keywords = [
16
16
  "non-strict",
17
17
  ]
18
18
  classifiers = [
19
- "Development Status :: 3 - Alpha",
19
+ "Development Status :: 4 - Beta",
20
20
  "Framework :: Pytest",
21
21
  "Intended Audience :: Developers",
22
22
  "License :: OSI Approved :: Apache Software License",
@@ -25,22 +25,24 @@ classifiers = [
25
25
  "Typing :: Typed",
26
26
  ]
27
27
  dependencies = [
28
- "pythonic-fp-booleans>=1.1.1",
29
- "pythonic-fp-circulararray>=5.3.2",
30
- "pythonic-fp-sentinels>=2.1.0",
28
+ "pythonic-fp-booleans>=2.1.1",
29
+ "pythonic-fp-circulararray>=6.0.1",
30
+ "pythonic-fp-gadgets>=4.0.2",
31
31
  ]
32
32
  dynamic = ["description"]
33
33
 
34
34
  [project.urls]
35
35
  Changelog = "https://github.com/grscheller/pythonic-fp-fptools/blob/main/CHANGELOG.rst"
36
- Documentation = "https://grscheller.github.io/pythonic-fp/fptools/development/build/html/releases.html"
37
- Homepage = "https://github.com/grscheller/pythonic-fp/blob/main/README.md"
36
+ Documentation = "https://grscheller.github.io/pythonic-fp/fptools/development/build/html/"
37
+ Homepage = "https://grscheller.github.io/pythonic-fp/homepage/build/html/"
38
38
  Source = "https://github.com/grscheller/pythonic-fp-fptools"
39
39
 
40
40
  [project.optional-dependencies]
41
41
  test = [
42
42
  "pytest>=8.4.1",
43
- "pythonic-fp-containers>=3.0.0",
43
+ "pythonic-fp-containers>=4.0.1",
44
+ "pythonic-fp-iterables>=5.1.3",
45
+ "pythonic-fp-queues>=5.1.1",
44
46
  ]
45
47
 
46
48
  [build-system]
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __all__ = ['Either', 'LEFT', 'RIGHT']
15
+ __all__ = ['Either', 'EitherBool', 'LEFT', 'RIGHT']
16
16
 
17
17
  from collections.abc import Callable, Iterator, Sequence
18
18
  from typing import cast, overload
@@ -21,6 +21,12 @@ from .maybe import MayBe
21
21
 
22
22
 
23
23
  class EitherBool(SBool):
24
+ """Boolean-like type used by Either constructor.
25
+
26
+ - A "truthy" value passed to constructor produces the unique ``LEFT`` value.
27
+ - A "falsy" value passed to constructor produces the unique ``RIGHT`` value.
28
+
29
+ """
24
30
  def __repr__(self) -> str:
25
31
  if self:
26
32
  return 'LEFT'
@@ -28,36 +34,38 @@ class EitherBool(SBool):
28
34
 
29
35
 
30
36
  LEFT = EitherBool(True)
37
+ """Singleton value signaling ``Either`` constructor to produce a ``LEFT`` Either, the default."""
38
+
31
39
  RIGHT = EitherBool(False)
40
+ """Singleton value signaling ``Either`` constructor to produce a ``RIGHT`` Either."""
32
41
 
33
42
 
34
43
  class Either[L, R]:
35
44
  """
36
- Either Monad
37
- ------------
45
+ .. admonition:: Either Monad
38
46
 
39
- Data structure semantically containing either a left
40
- or a right value, but not both.
47
+ Data structure semantically containing either a left
48
+ or a right value, but not both.
41
49
 
42
- Implements a left biased Either Monad.
50
+ Implements a left biased Either Monad.
43
51
 
44
- - ``Either(value: +L, LEFT)`` produces a left ``Either``
45
- - ``Either(value: +L, RIGHT)`` produces a right ``Either``
52
+ - ``Either(value: +L, LEFT)`` produces a left ``Either``
53
+ - ``Either(value: +L, RIGHT)`` produces a right ``Either``
46
54
 
47
- In a Boolean context
55
+ In a Boolean context
48
56
 
49
- - A left ``Either`` is "truthy"
50
- - A right ``Either`` is "falsy"
57
+ - A left ``Either`` is "truthy"
58
+ - A right ``Either`` is "falsy"
51
59
 
52
- Two ``Either`` objects compare as equal when
60
+ Two ``Either`` objects compare as equal when
53
61
 
54
- - both are left values or both are right values whose values
62
+ - both are left values or both are right values whose values
55
63
 
56
- - are the same object
57
- - compare as equal
64
+ - are the same object
65
+ - compare as equal
58
66
 
59
- Immutable, an ``Either`` does not change after being created.
60
- Therefore ``map`` & ``bind`` return new instances.
67
+ Immutable, an ``Either`` does not change after being created.
68
+ Therefore ``map`` & ``bind`` return new instances.
61
69
 
62
70
  .. warning::
63
71
 
@@ -4,7 +4,7 @@ from collections.abc import Callable, Iterator, Sequence
4
4
  from pythonic_fp.booleans.subtypable import SBool
5
5
  from typing import overload
6
6
 
7
- __all__ = ['Either', 'LEFT', 'RIGHT']
7
+ __all__ = ['Either', 'EitherBool', 'LEFT', 'RIGHT']
8
8
 
9
9
  class EitherBool(SBool): ...
10
10
 
@@ -13,32 +13,28 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- FP tools for functions
17
- ======================
16
+ .. admonition:: FP tools for functions
18
17
 
19
- FP utilities to manipulate and partially apply functions
18
+ FP utilities to manipulate and partially apply functions.
20
19
 
21
- - *function* **swap** - Swap the arguments of a 2 argument function
22
- - *function* **sequenced** - Convert function to take a sequence of its arguments
23
- - *function* **negate** - Transforms a predicate to its negation
24
- - *function* **partial** - Returns a partially applied function
20
+ - *function* **swap** - Swap the arguments of a 2 argument function
21
+ - *function* **compose** - Function composition
22
+ - *function* **negate** - Transforms a predicate to its negation
23
+ - *function* **sequenced** - Convert function to take a sequence of its arguments
24
+ - *function* **partial** - Returns a partially applied function
25
25
 
26
26
  """
27
27
 
28
28
  from collections.abc import Callable
29
29
  from typing import Any, ParamSpec
30
30
 
31
- __all__ = ['swap', 'sequenced', 'partial', 'negate']
31
+ __all__ = ['swap', 'compose', 'negate', 'sequenced', 'partial']
32
32
 
33
33
  P = ParamSpec('P')
34
34
 
35
35
 
36
36
  def swap[U, V, R](f: Callable[[U, V], R]) -> Callable[[V, U], R]:
37
- """
38
- Swap args
39
- ---------
40
-
41
- Swap arguments of a two argument function.
37
+ """Swap arguments of a two argument function.
42
38
 
43
39
  :param f: Two argument function.
44
40
  :returns: A version of ``f`` with its arguments swapped.
@@ -47,17 +43,23 @@ def swap[U, V, R](f: Callable[[U, V], R]) -> Callable[[V, U], R]:
47
43
  return lambda v, u: f(u, v)
48
44
 
49
45
 
50
- def negate[**P](f: Callable[P, bool]) -> Callable[P, bool]:
46
+ def compose[D, T, R](f: Callable[[D], T], g: Callable[[T], R]) -> Callable[[D], R]:
47
+ """Function Composition
48
+
49
+ :param f: Function called first with domain D and range T.
50
+ :param g: Function called on result with domain T and range R.
51
+ :returns: The composite function g∘f(d) = g(f(d))
52
+
51
53
  """
52
- Negate predicate
53
- ----------------
54
+ return lambda d: g(f(d))
55
+
54
56
 
55
- Take a predicate and return its negation.
57
+ def negate[**P](f: Callable[P, bool]) -> Callable[P, bool]:
58
+ """Take a predicate and return its negation.
56
59
 
57
60
  :param f: a function ``f`` which returns a bool
58
61
  :returns: the function ``not f``
59
62
  """
60
-
61
63
  def ff(*args: P.args, **kwargs: P.kwargs) -> bool:
62
64
  return not f(*args, **kwargs)
63
65
 
@@ -65,9 +67,7 @@ def negate[**P](f: Callable[P, bool]) -> Callable[P, bool]:
65
67
 
66
68
 
67
69
  def sequenced[R](f: Callable[..., R]) -> Callable[[tuple[Any]], R]:
68
- """
69
- Multi-to-single valued
70
- ----------------------
70
+ """Convert a function from multi-to-single valued.
71
71
 
72
72
  Convert a function with arbitrary positional arguments to one taking
73
73
  a tuple of the original arguments.
@@ -80,7 +80,6 @@ def sequenced[R](f: Callable[..., R]) -> Callable[[tuple[Any]], R]:
80
80
  TODO: Look into replacing this function with a Callable class?
81
81
 
82
82
  """
83
-
84
83
  def ff(tupled_args: tuple[Any]) -> R:
85
84
  return f(*tupled_args)
86
85
 
@@ -88,9 +87,7 @@ def sequenced[R](f: Callable[..., R]) -> Callable[[tuple[Any]], R]:
88
87
 
89
88
 
90
89
  def partial[**P, R](f: Callable[P, R], *args: Any) -> Callable[..., R]:
91
- """
92
- Partial application
93
- -------------------
90
+ """Partial function application.
94
91
 
95
92
  Partially apply arguments to a function, left to right.
96
93
 
@@ -98,7 +95,6 @@ def partial[**P, R](f: Callable[P, R], *args: Any) -> Callable[..., R]:
98
95
  - best practice is to cast the result immediately
99
96
 
100
97
  """
101
-
102
98
  def finish(*rest: Any) -> R:
103
99
  return sequenced(f)(args + rest)
104
100
 
@@ -1,11 +1,12 @@
1
1
  from collections.abc import Callable
2
2
  from typing import Any, ParamSpec
3
3
 
4
- __all__ = ['swap', 'sequenced', 'partial', 'negate']
4
+ __all__ = ['swap', 'compose', 'negate', 'sequenced', 'partial']
5
5
 
6
6
  P = ParamSpec('P')
7
7
 
8
8
  def swap[U, V, R](f: Callable[[U, V], R]) -> Callable[[V, U], R]: ...
9
+ def compose[D, T, R](f: Callable[[D], T], g: Callable[[T], R]) -> Callable[[D], R]: ...
9
10
  def negate[**P](f: Callable[P, bool]) -> Callable[P, bool]: ...
10
11
  def sequenced[R](f: Callable[..., R]) -> Callable[[tuple[Any]], R]: ...
11
12
  def partial[**P, R](f: Callable[P, R], *args: Any) -> Callable[..., R]: ...
@@ -13,17 +13,16 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """
16
- Lazy function evaluation
17
- ========================
16
+ .. admonition:: Lazy function evaluation
18
17
 
19
- Delayed function evaluations. FP tools for "non-strict" function evaluations.
20
- Useful to delay a function's evaluation until some inner scope.
18
+ Delayed function evaluations. FP tools for "non-strict" function evaluations.
19
+ Useful to delay a function's evaluation until some inner scope.
21
20
 
22
- Non-strict delayed function evaluation.
21
+ Non-strict delayed function evaluation.
23
22
 
24
- - *class* **Lazy** - Delay evaluation of functions taking & returning single values
25
- - *function* **lazy** - Delay evaluation of functions taking any number of values
26
- - *function* **real_lazy** - Version of ``lazy`` which caches its result
23
+ - *class* **Lazy** - Delay evaluation of functions taking & returning single values
24
+ - *function* **lazy** - Delay evaluation of functions taking any number of values
25
+ - *function* **real_lazy** - Version of ``lazy`` which caches its result
27
26
 
28
27
  """
29
28
 
@@ -38,14 +37,13 @@ __all__ = ['Lazy', 'lazy', 'real_lazy']
38
37
 
39
38
  class Lazy[D, R]:
40
39
  """
41
- Non-strict function evaluation
42
- ------------------------------
40
+ .. admonition:: Non-strict function evaluation
43
41
 
44
- Delayed evaluation of a singled valued function.
42
+ Delayed evaluation of a singled valued function.
45
43
 
46
- Class instance delays the executable of a function where ``Lazy(f, arg)``
47
- constructs an object that can evaluate the Callable ``f`` with its argument
48
- at a later time.
44
+ Class instance delays the executable of a function where ``Lazy(f, arg)``
45
+ constructs an object that can evaluate the Callable ``f`` with its argument
46
+ at a later time.
49
47
 
50
48
  .. note::
51
49
 
@@ -153,11 +151,10 @@ def lazy[**P, R](
153
151
  f: Callable[P, R], *args: P.args, **kwargs: P.kwargs
154
152
  ) -> Lazy[tuple[Any, ...], R]:
155
153
  """
156
- Delayed evaluations
157
- -------------------
154
+ .. admonition:: Delayed evaluations
158
155
 
159
- Function returning a delayed evaluation of a function of an arbitrary number
160
- of positional arguments.
156
+ Function returning a delayed evaluation of a function of an arbitrary number
157
+ of positional arguments.
161
158
 
162
159
  :param f: Function whose evaluation is to be delayed.
163
160
  :param args: Positional arguments to be passed to ``f``.
@@ -172,11 +169,10 @@ def real_lazy[**P, R](
172
169
  f: Callable[P, R], *args: P.args, **kwargs: P.kwargs
173
170
  ) -> Lazy[tuple[Any, ...], R]:
174
171
  """
175
- Cached Delayed evaluations
176
- --------------------------
172
+ .. admonition:: Cached Delayed evaluations
177
173
 
178
- Function returning a delayed evaluation of a function of an arbitrary number
179
- of positional arguments. Evaluation is cached.
174
+ Function returning a delayed evaluation of a function of an
175
+ arbitrary number of positional arguments. Evaluation is cached.
180
176
 
181
177
  :param f: Function whose evaluation is to be delayed.
182
178
  :param args: Positional arguments to be passed to ``f``.
@@ -18,23 +18,22 @@ __all__ = ['MayBe']
18
18
 
19
19
  from collections.abc import Callable, Iterator, Sequence
20
20
  from typing import cast, Final, overload
21
- from pythonic_fp.sentinels.flavored import Sentinel
21
+ from pythonic_fp.gadgets.sentinels.flavored import Sentinel
22
22
 
23
23
 
24
24
  class MayBe[D]:
25
25
  """
26
- Maybe Monad
27
- -----------
26
+ .. admonition:: Maybe Monad
28
27
 
29
- Data structure wrapping a potentially missing item.
28
+ Data structure wrapping a potentially missing item.
30
29
 
31
- Immutable semantics
30
+ Immutable semantics
32
31
 
33
- - can store any item of any type, including ``None``
32
+ - can store any item of any type, including ``None``
34
33
 
35
- - with one hidden implementation dependent exception
34
+ - with one hidden implementation dependent exception
36
35
 
37
- - immutable semantics, therefore covariant
36
+ - immutable semantics
38
37
 
39
38
  .. warning::
40
39
 
@@ -20,17 +20,16 @@ from pythonic_fp.circulararray.auto import CA
20
20
 
21
21
  class State[S, A]:
22
22
  """
23
- State Monad
24
- -----------
23
+ .. admonition:: State Monad
25
24
 
26
- Data structure generating values while propagating changes of state.
27
- A pure FP implementation for the State Monad
25
+ Data structure generating values while propagating changes of state.
26
+ A pure FP implementation for the State Monad
28
27
 
29
- - class ``State`` represents neither a state nor (value, state) pair
28
+ - class ``State`` represents neither a state nor a (value, state) pair
30
29
 
31
- - it wraps a transformation old_state -> (value, new_state)
32
- - the ``run`` method is this wrapped transformation
33
- - ``bind`` is just state propagating function composition
30
+ - it wraps a transformation old_state -> (value, new_state)
31
+ - the ``run`` method is this wrapped transformation
32
+ - ``bind`` is just state propagating function composition
34
33
 
35
34
  """
36
35
 
@@ -15,7 +15,7 @@
15
15
  from typing import Final
16
16
  from pythonic_fp.containers.functional_tuple import FTuple
17
17
  from pythonic_fp.fptools.either import Either, LEFT, RIGHT
18
- from pythonic_fp.containers.queues.fifo import FIFOQueue
18
+ from pythonic_fp.queues.fifo import FIFOQueue
19
19
 
20
20
 
21
21
  class TestEitherSequence:
@@ -14,7 +14,7 @@
14
14
 
15
15
  from pythonic_fp.containers.functional_tuple import FTuple
16
16
  from pythonic_fp.fptools.maybe import MayBe
17
- from pythonic_fp.containers.queues.de import DEQueue, de_queue
17
+ from pythonic_fp.queues.de import DEQueue, de_queue
18
18
 
19
19
 
20
20
  class Test_MB_sequence: