You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/effectful_but_side_effect_free.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ In functional programming, programs are built by composing functions that have n
5
5
-`pfun.effect` helps you work with side-effects in functional style.
6
6
7
7
8
-
If you have some experience with functionl programming, you can probably skip ahead to the section on `pfun.effect.Effect`.
8
+
If you have some experience with functional programming, you can probably skip ahead to the section on `pfun.effect.Effect`.
9
9
## Maybe
10
10
The job of the `pfun.maybe.Maybe` type is to help you work with missing values, in much the same way that the built-in `None` type is used. One of the main disadvantages of the `None` type is that you end up with logic for dealing with missing values all over the place, using code like `if foo is not None`.
Copy file name to clipboardExpand all lines: docs/immutable_objects_and_data.md
+78Lines changed: 78 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,3 +69,81 @@ assert 'new_key' not in d and d2.get('new_key') == Just('new_value')
69
69
70
70
It supports the same api as `dict` which the exception of `__setitem__` which will raise an exception, and uses
71
71
`pfun.maybe.Maybe` to indicate the presence or absence of a key when using `get`.
72
+
73
+
## Lens
74
+
Working with deeply nested immutable data-structures can be tricky when you want to transform only one member of an object deep inside the nested structure, but want to keep other the remaining data-structure intact, for example in:
75
+
76
+
```python
77
+
d = {
78
+
'a': {
79
+
'b': {
80
+
'c': 'I want to change this...'
81
+
}
82
+
},
83
+
'd': 'but not this'
84
+
}
85
+
new_d = d.copy()
86
+
new_d['a'] = d['a'].copy()
87
+
new_d['a']['b'] = d['a']['b'].copy()
88
+
new_d['a']['b']['c'] ='Phew! That took a lot of work!'
89
+
```
90
+
A _lens_ is a setter function that takes as arguments a value to replace at some path/index
91
+
in an object/data-structure, and an object to transform. `pfun.lens` allows you
92
+
to easily construct these setter functions by specifying the path/index at
93
+
which you want to perform a replacement using normal Python indexing and attribute
94
+
access. You use the object returned by `lens()` as a proxy for the object you want
95
+
to transform by accessing attributes and indexes on it. The lens will remember this
96
+
path, and use it when performing an update. You perform an update by calling the lens
97
+
with the value to use as a replacement, and an object on which to perform the replacement:
98
+
```python
99
+
from pfun import lens
100
+
101
+
102
+
t = lens()['a']['b']['c']
103
+
new_d = t('Wow that was a lot easier!')(d)
104
+
assert new_d['a']['b']['c'] =='Wow that was a lot easier!'
105
+
```
106
+
If you use the `pfun` MyPy plugin, you can give a type as an argument to `lens`, which allows MyPy to check that the operations you make on the lens object are supported by the type you intend to transform:
107
+
```python
108
+
classPerson:
109
+
name: str
110
+
111
+
112
+
classUser(Person):
113
+
organization: Organization
114
+
115
+
116
+
u = lens(User)
117
+
118
+
# MyPy type error because we misspelled 'organization'
119
+
u.organisation('Foo Inc')
120
+
121
+
# MyPy type error because "User.organization" must a "str"
122
+
u.organization(0)
123
+
124
+
# MyPy type error because "Person" is not a "User"
125
+
u.organization('Foo Inc')(Person())
126
+
```
127
+
Since lenses are just Python callables, you can combine them using the normal
Copy file name to clipboardExpand all lines: docs/useful_functions.md
+39-33Lines changed: 39 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,6 @@
1
1
## curry
2
-
`curry` makes it easy to [curry](https://en.wikipedia.org/wiki/Currying) functions while inferring the resulting type signature with MyPy (if the `pfun` MyPy plugin is enabled).
2
+
`curry` makes it easy to [curry](https://en.wikipedia.org/wiki/Currying) functions. If you enable the MyPy plugin, MyPy can also
3
+
type check the arguments and return types of curried functions.
3
4
4
5
The functions returned by `curry` support both normal and curried call styles:
To keep things simple, the actual signature of curried functions is simply the original function signature,
31
+
which allows you to pass curried functions as arguments to functions that expects callbacks:
29
32
30
-
To keep things simple, the `pfun` MyPy plugin doesn't infer all possible overloads of curried signatures. Instead, the inferred signature is split into the following argument lists: One argument list for optional arguments and `**kwargs` followed by one argument list for each positional argument. If the uncurried function accepts `*args`, it's added to the last positional argument list of the curried function
Currently the `curry` MyPy plugin doesn't support methods. If you want to return a curried function from a method you can use the following workaround:
0 commit comments