Skip to content

Commit d9c7519

Browse files
committed
More docs about combinators
1 parent 4663603 commit d9c7519

File tree

4 files changed

+140
-19
lines changed

4 files changed

+140
-19
lines changed

doc/Combinators.md

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
# Combinators
22
**Contents**
3-
- [\*N combinators](#\*N-combinators)
3+
- [N combinators](#N-combinators)
44
- [Introduction](#Introduction)
55
- [Omit values from tuple or shape](#Omit-values-from-tuple-or-shape)
66
- [Ctor function](#Ctor-function)
77
- [Caveats](#Caveats)
8-
- [\*KV combinators](#\*KV-combinators)
8+
- [KV combinators](#KV-combinators)
99
- [Map](#Map)
1010
- [Functions](#Functions)
11+
- [T combinators](#T-combinators)
1112

12-
# \*N combinators
13+
# N combinators
1314

1415
- #### Introduction
1516

@@ -38,7 +39,8 @@ use function Fp\Collection\sequenceOptionT;
3839
use function Fp\Evidence\proveArray;
3940
use function Fp\Evidence\proveBool;
4041
use function Fp\Evidence\proveInt;
41-
use function Fp\Json\jsonDecode;
42+
use function Fp\Util\jsonDecode;
43+
use function Fp\Callable\ctor;
4244

4345
$json = <<<JSON
4446
{
@@ -60,7 +62,10 @@ function fooFromJson(string $json): Option
6062
fn() => at($data, 'b')->flatMap(proveBool(...)),
6163
fn() => at($data, 'c')->flatMap(proveBool(...)),
6264
))
63-
->mapN(fn(int $a, bool $b, bool $c) => new Foo($a, $b, $c));
65+
->mapN(ctor(Foo::class));
66+
67+
// or more verbose version:
68+
// ->mapN(fn(int $a, bool $b, bool $c) => new Foo($a, $b, $c));
6469
}
6570
```
6671

@@ -128,7 +133,7 @@ three parameters. This is non-valid case and Psalm tells about it.
128133

129134
- #### Ctor function
130135

131-
There is useful function `Fp\Callable\ctor` that is friend of \*N
136+
There is useful function `Fp\Callable\ctor` that is friend of N
132137
combinators. Examples above can be rewritten as follows:
133138

134139
``` php
@@ -158,8 +163,8 @@ unnecessary args, psalm issues)
158163

159164
- #### Caveats
160165

161-
For shapes with string keys the `Fp\Callable\ctor` and \*N combinators
162-
use `ReflectionFunction` but for tuples not.
166+
For shapes with string keys the `Fp\Callable\ctor` and N combinators use
167+
`ReflectionFunction` but for tuples not.
163168

164169
For tuples reflection is unnecessary because PHP allows to pass extra
165170
arguments to functions with array spread:
@@ -205,15 +210,15 @@ test(...['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]);
205210
So `ReflectionFunction` used for filtering extra arguments before array
206211
will be spread.
207212

208-
# \*KV combinators
213+
# KV combinators
209214

210215
- #### Map
211216

212217
Before v5 `Fp\Collections\Map` used `Fp\Collections\Entry` to represents
213218
kv pair. It was unfriendly for ide (lack autocompletion ability).
214219

215220
Since v5 `Fp\Collections\Entry` has been removed. Instead, each method
216-
of `Fp\Collections\Map` has \*KV version:
221+
of `Fp\Collections\Map` has KV version:
217222

218223
``` php
219224
<?php
@@ -244,7 +249,7 @@ time.
244249

245250
- #### Functions
246251

247-
Regular functions has \*KV combinators too:
252+
Regular functions has KV combinators too:
248253

249254
``` php
250255
<?php
@@ -272,3 +277,60 @@ function sumWithKeys(array $hashMap): HashMap
272277
return mapKV($hashMap, fn(int $key, int $value) => $key + $value);
273278
}
274279
```
280+
281+
Keys were passed as the second parameter $callback/$predicate prior to
282+
v5. At first glance, it was convenient. This leads to such problems:
283+
<https://psalm.dev/r/f00c0b19be>. But with v5 there is no problem
284+
anymore: <https://psalm.dev/r/20e91dfded>.
285+
286+
# T combinators
287+
288+
That combinators accepts varargs as input and return tuples.
289+
290+
`Fp\Collection\partitionT`:
291+
292+
``` php
293+
<?php
294+
295+
use Tests\Mock\Foo;
296+
use Tests\Mock\Bar;
297+
use Tests\Mock\Baz;
298+
299+
use function Fp\Collection\partitionT;
300+
301+
/**
302+
* @param list<Foo|Bar|Baz> $list
303+
* @return array{list<Foo>, list<Bar>, list<Baz>}
304+
*/
305+
function example(array $list): array
306+
{
307+
return partitionT($list, fn($i) => $i instanceof Foo, fn($i) => $i instanceof Bar);
308+
}
309+
```
310+
311+
`Fp\Collection\sequenceOptionT`:
312+
313+
``` php
314+
<?php
315+
316+
use Fp\Functional\Option\Option;
317+
318+
use function Fp\Evidence\proveInt;
319+
use function Fp\Evidence\proveString;
320+
use function Fp\Collection\sequenceOptionT;
321+
use function Fp\Collection\at;
322+
323+
/**
324+
* @param array<string, mixed> $data
325+
* @return Option<array{string, int}>
326+
*/
327+
function sequenceT(array $data): Option
328+
{
329+
return sequenceOptionT(
330+
at($data, 'name')->flatMap(proveString(...)),
331+
at($data, 'age')->flatMap(proveInt(...)),
332+
);
333+
}
334+
```
335+
336+
And others.

src/Doc/Md/Combinators/1_N_combinators.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# *N combinators
1+
# N combinators
22
- #### Introduction
33

44
There are useful combinators for working with shape and tuples:
@@ -24,7 +24,8 @@ use function Fp\Collection\sequenceOptionT;
2424
use function Fp\Evidence\proveArray;
2525
use function Fp\Evidence\proveBool;
2626
use function Fp\Evidence\proveInt;
27-
use function Fp\Json\jsonDecode;
27+
use function Fp\Util\jsonDecode;
28+
use function Fp\Callable\ctor;
2829

2930
$json = <<<JSON
3031
{
@@ -46,7 +47,10 @@ function fooFromJson(string $json): Option
4647
fn() => at($data, 'b')->flatMap(proveBool(...)),
4748
fn() => at($data, 'c')->flatMap(proveBool(...)),
4849
))
49-
->mapN(fn(int $a, bool $b, bool $c) => new Foo($a, $b, $c));
50+
->mapN(ctor(Foo::class));
51+
52+
// or more verbose version:
53+
// ->mapN(fn(int $a, bool $b, bool $c) => new Foo($a, $b, $c));
5054
}
5155
```
5256

@@ -112,7 +116,7 @@ This is non-valid case and Psalm tells about it.
112116

113117
- #### Ctor function
114118

115-
There is useful function `Fp\Callable\ctor` that is friend of *N combinators. Examples above can be rewritten as follows:
119+
There is useful function `Fp\Callable\ctor` that is friend of N combinators. Examples above can be rewritten as follows:
116120

117121
```php
118122
<?php
@@ -139,7 +143,7 @@ That function supports all features meant above (skip unnecessary args, psalm is
139143

140144
- #### Caveats
141145

142-
For shapes with string keys the `Fp\Callable\ctor` and *N combinators use `ReflectionFunction` but for tuples not.
146+
For shapes with string keys the `Fp\Callable\ctor` and N combinators use `ReflectionFunction` but for tuples not.
143147

144148
For tuples reflection is unnecessary because PHP allows to pass extra arguments to functions with array spread:
145149

src/Doc/Md/Combinators/2_KV_combinators.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# *KV combinators
1+
# KV combinators
22

33
- #### Map
44

55
Before v5 `Fp\Collections\Map` used `Fp\Collections\Entry` to represents kv pair.
66
It was unfriendly for ide (lack autocompletion ability).
77

8-
Since v5 `Fp\Collections\Entry` has been removed. Instead, each method of `Fp\Collections\Map` has *KV version:
8+
Since v5 `Fp\Collections\Entry` has been removed. Instead, each method of `Fp\Collections\Map` has KV version:
99

1010
```php
1111
<?php
@@ -35,7 +35,7 @@ This makes sense since the key and value are rarely needed at the same time.
3535

3636
- #### Functions
3737

38-
Regular functions has *KV combinators too:
38+
Regular functions has KV combinators too:
3939

4040
```php
4141
<?php
@@ -63,3 +63,7 @@ function sumWithKeys(array $hashMap): HashMap
6363
return mapKV($hashMap, fn(int $key, int $value) => $key + $value);
6464
}
6565
```
66+
67+
Keys were passed as the second parameter $callback/$predicate prior to v5.
68+
At first glance, it was convenient. This leads to such problems: https://psalm.dev/r/f00c0b19be.
69+
But with v5 there is no problem anymore: https://psalm.dev/r/20e91dfded.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# T combinators
2+
3+
That combinators accepts varargs as input and return tuples.
4+
5+
`Fp\Collection\partitionT`:
6+
7+
```php
8+
<?php
9+
10+
use Tests\Mock\Foo;
11+
use Tests\Mock\Bar;
12+
use Tests\Mock\Baz;
13+
14+
use function Fp\Collection\partitionT;
15+
16+
/**
17+
* @param list<Foo|Bar|Baz> $list
18+
* @return array{list<Foo>, list<Bar>, list<Baz>}
19+
*/
20+
function example(array $list): array
21+
{
22+
return partitionT($list, fn($i) => $i instanceof Foo, fn($i) => $i instanceof Bar);
23+
}
24+
```
25+
26+
`Fp\Collection\sequenceOptionT`:
27+
28+
```php
29+
<?php
30+
31+
use Fp\Functional\Option\Option;
32+
33+
use function Fp\Evidence\proveInt;
34+
use function Fp\Evidence\proveString;
35+
use function Fp\Collection\sequenceOptionT;
36+
use function Fp\Collection\at;
37+
38+
/**
39+
* @param array<string, mixed> $data
40+
* @return Option<array{string, int}>
41+
*/
42+
function sequenceT(array $data): Option
43+
{
44+
return sequenceOptionT(
45+
at($data, 'name')->flatMap(proveString(...)),
46+
at($data, 'age')->flatMap(proveInt(...)),
47+
);
48+
}
49+
```
50+
51+
And others.

0 commit comments

Comments
 (0)