Skip to content

Commit 1f9aa2f

Browse files
committed
More docs about Monads
1 parent d9c7519 commit 1f9aa2f

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

doc/Monads.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- [Examples](#Examples)
77
- [Type assertions with Option](#Type-assertions-with-Option)
88
- [Filter chaining](#Filter-chaining)
9+
- [Filter Option](#Filter-Option)
10+
- [List of all errors](#List-of-all-errors)
11+
- [Traverse](#Traverse)
912

1013
# Option monad
1114

@@ -334,4 +337,82 @@ function filterTGenericObjectTypeParam(Atomic $atomic): Option
334337
default => null
335338
}));
336339
}
340+
```
341+
342+
- #### Filter Option
343+
344+
If you want to apply an operation that returns `Option` for each element
345+
and collect only `Option::some` use `filterMap`:
346+
347+
``` php
348+
<?php
349+
350+
use Fp\Collections\ArrayList;
351+
use Fp\Functional\Option\Option;
352+
353+
// Inferred as ArrayList<int>
354+
// Result is ArrayList(3, 4, 5, 6, 7)
355+
$result = ArrayList::collect([1, 2, 3, 4, 5, 6, 7])
356+
->filterMap(fn($i) => $i > 5 ? Option::none() : Option::some($i + 2));
357+
```
358+
359+
- #### List of all errors
360+
361+
If you want to apply an operation that returns `Either` for each element
362+
and want collect all errors, use can use `partitionMap`+`toEither`
363+
364+
``` php
365+
<?php
366+
367+
use Fp\Collections\ArrayList;
368+
use Fp\Functional\Either\Either;
369+
370+
// Inferred as Either<ArrayList<string>, ArrayList<int>>
371+
// Result is Left(ArrayList('6 is greater than 5', '7 is greater than 5'))
372+
$result = ArrayList::collect([1, 2, 3, 4, 5, 6, 7])
373+
->partitionMap(
374+
fn($i) => $i > 5
375+
? Either::left("{$i} is greater than 5")
376+
: Either::right($i),
377+
)
378+
->toEither();
379+
```
380+
381+
- #### Traverse
382+
383+
If you want to apply operation for each element, but `$callback` returns
384+
`Option` or `Either`, use can use `traverseOption`/`traverseEither`:
385+
386+
``` php
387+
<?php
388+
389+
use Fp\Collections\ArrayList;
390+
use Fp\Functional\Option\Option;
391+
use Tests\Mock\Foo;
392+
use Tests\Mock\Bar;
393+
394+
/**
395+
* @param ArrayList<Foo|Bar> $list
396+
* @return Option<ArrayList<Foo>>
397+
*/
398+
function assertAllFoo(ArrayList $list): Option
399+
{
400+
return $list->traverseOption(
401+
fn(Foo|Bar $item) => $item instanceof Foo
402+
? Option::some($item)
403+
: Option::none(),
404+
);
405+
}
406+
407+
$fooAndBarItems = ArrayList::collect([new Foo(a: 42), new Bar(a: true)]);
408+
409+
// Inferred type ArrayList<Foo>
410+
// Result is ArrayList()
411+
$noItems = assertAllFoo($items)->getOrElse(ArrayList::empty());
412+
413+
$fooItems = ArrayList::collect([new Foo(a: 42), new Foo(a: 43)]);
414+
415+
// Inferred type ArrayList<Foo>
416+
// Result is ArrayList(Foo(a: 42), Foo(a: 43))
417+
$noItems = assertAllFoo($fooItems)->getOrElse(ArrayList::empty());
337418
```

src/Doc/Md/Monads/4_Examples.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,75 @@ function filterTGenericObjectTypeParam(Atomic $atomic): Option
122122
}
123123
```
124124

125+
- #### Filter Option
126+
If you want to apply an operation that returns `Option` for each element and collect only `Option::some` use `filterMap`:
127+
128+
```php
129+
<?php
130+
131+
use Fp\Collections\ArrayList;
132+
use Fp\Functional\Option\Option;
133+
134+
// Inferred as ArrayList<int>
135+
// Result is ArrayList(3, 4, 5, 6, 7)
136+
$result = ArrayList::collect([1, 2, 3, 4, 5, 6, 7])
137+
->filterMap(fn($i) => $i > 5 ? Option::none() : Option::some($i + 2));
138+
```
139+
140+
- #### List of all errors
141+
142+
If you want to apply an operation that returns `Either` for each element and want collect all errors, use can use `partitionMap`+`toEither`
143+
```php
144+
<?php
145+
146+
use Fp\Collections\ArrayList;
147+
use Fp\Functional\Either\Either;
148+
149+
// Inferred as Either<ArrayList<string>, ArrayList<int>>
150+
// Result is Left(ArrayList('6 is greater than 5', '7 is greater than 5'))
151+
$result = ArrayList::collect([1, 2, 3, 4, 5, 6, 7])
152+
->partitionMap(
153+
fn($i) => $i > 5
154+
? Either::left("{$i} is greater than 5")
155+
: Either::right($i),
156+
)
157+
->toEither();
158+
```
159+
160+
- #### Traverse
161+
162+
If you want to apply operation for each element, but `$callback` returns `Option` or `Either`, use can use `traverseOption`/`traverseEither`:
163+
164+
```php
165+
<?php
166+
167+
use Fp\Collections\ArrayList;
168+
use Fp\Functional\Option\Option;
169+
use Tests\Mock\Foo;
170+
use Tests\Mock\Bar;
171+
172+
/**
173+
* @param ArrayList<Foo|Bar> $list
174+
* @return Option<ArrayList<Foo>>
175+
*/
176+
function assertAllFoo(ArrayList $list): Option
177+
{
178+
return $list->traverseOption(
179+
fn(Foo|Bar $item) => $item instanceof Foo
180+
? Option::some($item)
181+
: Option::none(),
182+
);
183+
}
184+
185+
$fooAndBarItems = ArrayList::collect([new Foo(a: 42), new Bar(a: true)]);
186+
187+
// Inferred type ArrayList<Foo>
188+
// Result is ArrayList()
189+
$noItems = assertAllFoo($items)->getOrElse(ArrayList::empty());
190+
191+
$fooItems = ArrayList::collect([new Foo(a: 42), new Foo(a: 43)]);
192+
193+
// Inferred type ArrayList<Foo>
194+
// Result is ArrayList(Foo(a: 42), Foo(a: 43))
195+
$noItems = assertAllFoo($fooItems)->getOrElse(ArrayList::empty());
196+
```

0 commit comments

Comments
 (0)