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: README.md
+66-27
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,8 @@
4
4
## Introduction
5
5
6
6
Functional programing is a fascinating concept.
7
-
The purpose of this library is to explore `Functors`, `Applicative Functors` and `Monads` in OOP PHP, and provide examples of real world use case.
7
+
The purpose of this library is to explore `Functors`, `Applicative Functors`
8
+
and `Monads` in OOP PHP, and provide examples of real world use case.
8
9
9
10
Monad types available in the project:
10
11
*`State Monad`
@@ -15,33 +16,36 @@ Monad types available in the project:
15
16
*`Reader Monad`
16
17
*`Writer Monad`
17
18
18
-
Exploring functional programing space I noticed that working with primitive values from PHP is very hard and complicates implementation of many functional structures.
19
+
Exploring functional programing space I noticed that working with primitive values from PHP
20
+
is very hard and complicates implementation of many functional structures.
19
21
To simplify this experience, set of higher order primitives is introduced in library:
20
22
*`Num`
21
23
*`Sum`
22
24
*`Product`
23
25
*`Stringg`
24
26
*`Listt` (a.k.a List Monad, since `list` is a protected keyword in PHP)
25
-
27
+
26
28
## Installation
27
29
28
30
```
29
31
composer require widmogrod/php-functional
30
32
```
31
33
32
34
## Development
33
-
34
35
This repository follows [semantic versioning concept](http://semver.org/).
35
-
If you want to contribute, just follow [GitHub workflow](https://guides.github.com/introduction/flow/) and open a pull request.
36
+
If you want to contribute, just follow [CONTRIBUTING.md](/CONTRIBUTING.md)
36
37
37
-
More information about changes you can find in [change log](/CHANGELOG.md)
38
38
39
39
## Testing
40
40
41
-
Quality assurance is brought to you by [PHPSpec](http://www.phpspec.net/)
41
+
Quality assurance is brought to you by:
42
+
-[PHPUnit](https://phpunit.de)
43
+
-[Eris](https://github.com/giorgiosironi/eris) - QuickCheck and property-based testing tools to the PHP and PHPUnit ecosystem.
44
+
-[PHP-CS-Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) - A tool to automatically fix PHP coding standards issues
42
45
43
46
```
44
47
composer test
48
+
composer fix
45
49
```
46
50
47
51
## Use Cases
@@ -51,7 +55,7 @@ You can find more use cases and examples in the [example directory](/example/).
51
55
Monad is Functor and Applicative. You could say that Monad implements Functor and Applicative.
Apply function on list of values and as a result, receive list of all possible combinations
73
77
of applying function from the left list to a value in the right one.
74
78
75
-
```haskell
79
+
```haskell
76
80
[(+3),(+4)] <*> [1, 2] == [4, 5, 5, 6]
77
81
```
78
82
79
-
```php
83
+
```php
80
84
use Widmogrod\Functional as f;
81
85
use Widmogrod\Primitive\Listt;
82
86
@@ -104,7 +108,7 @@ Using Maybe as an instance of Monoid simplifies concat and reduce operations by
104
108
Extracting from a list of uneven values can be tricky and produce nasty code full of `if (isset)` statements.
105
109
By combining List and Maybe Monad, this process becomes simpler and more readable.
106
110
107
-
```php
111
+
```php
108
112
use Widmogrod\Monad\Maybe;
109
113
use Widmogrod\Primitive\Listt;
110
114
@@ -138,7 +142,7 @@ This results in nasty `try catch` blocks and many of if statements.
138
142
Either Monad shows how we can fail gracefully without breaking the execution chain and making the code more readable.
139
143
The following example demonstrates combining the contents of two files into one. If one of those files does not exist the operation fails gracefully.
140
144
141
-
```php
145
+
```php
142
146
use Widmogrod\Functional as f;
143
147
use Widmogrod\Monad\Either;
144
148
@@ -164,7 +168,7 @@ assert($concat->extract() === 'File "aaa" does not exists');
164
168
### IO Monad
165
169
Example usage of `IO Monad`. Read input from `stdin`, and print it to `stdout`.
166
170
167
-
```php
171
+
```php
168
172
use Widmogrod\Monad\IO as IO;
169
173
use Widmogrod\Functional as f;
170
174
@@ -176,7 +180,7 @@ $readFromInput(Monad\Identity::of('Enter something and press <enter>'))->run();
176
180
### Writer Monad
177
181
The `Writer monad` is useful to keep logs in a pure way. Coupled with `filterM` for example, this allows you to know exactly why an element was filtered.
The `Reader monad` provides a way to share a common environment, such as configuration information or class instances, across multiple functions.
204
208
205
-
```php
209
+
```php
206
210
207
211
use Widmogrod\Monad\Reader as R;
208
212
use Widmogrod\Functional as f;
@@ -276,22 +280,57 @@ $result = $scenario->Run([
276
280
]);
277
281
```
278
282
279
-
### Sequencing Monad operations
280
-
This variant of `sequence_` ignores the result.
283
+
##Haskell `do notation` in PHP
284
+
Why Haskell's do notation is interesting?
281
285
282
-
```php
283
-
use Widmogrod\Monad\IO as IO;
284
-
use Widmogrod\Functional as f;
286
+
In Haskell is just an "syntax sugar" and in many ways is not needed,
287
+
but in PHP control flow of monads can be hard to track.
288
+
289
+
Consider example, that use only chaining `bind()`
290
+
and compare it to the same version but with `do notation` in PHP.
291
+
292
+
### Control flow without do notation
285
293
286
-
f\sequence_([
287
-
IO\putStrLn('Your name:'),
288
-
IO\getLine(),
289
-
IO\putStrLn('Your surname:'),
290
-
IO\getLine(),
291
-
IO\putStrLn('Thank you'),
292
-
])->run();
294
+
```php
295
+
$result = Identity::of(1)
296
+
->bind(function ($a) {
297
+
return Identity::of(3)
298
+
->bind(function ($b) use ($a) {
299
+
return Identity::of($a + $b)
300
+
->bind(function ($c) {
301
+
return Identity::of($c * $c);
302
+
});
303
+
});
304
+
});
305
+
306
+
$this->assertEquals(Identity::of(16), $result);
293
307
```
294
308
309
+
### Control flow with do notation
310
+
311
+
```php
312
+
$result = doo(
313
+
let('a', Identity::of(1)),
314
+
let('b', Identity::of(3)),
315
+
let('c', in(['a', 'b'], function (int $a, int $b): Identity {
316
+
return Identity::of($a + $b);
317
+
})),
318
+
in(['c'], function (int $c): Identity {
319
+
return Identity::of($c * $c);
320
+
})
321
+
);
322
+
323
+
assert($result === Identity::of(16));
324
+
```
325
+
326
+
Everyone needs to judge by itself, but in my opinion `do notation`improve readability of code in PHP.
327
+
328
+
#### Book `Functional PHP` by Gilles Crettenand <ahref="https://www.packtpub.com/application-development/functional-php"><imgalign="right"height="160"src="functional-php.png"></a>
329
+
330
+
In recently published book [`Functional PHP` by Gilles Crettenand](https://www.packtpub.com/application-development/functional-php), you can learn more applications of `widmogrod/php-functional`, see how it compares to other projects and how in an effortless way apply functional thinking in daily work.
331
+
332
+
[Buy the book at PacktPub](https://www.packtpub.com/application-development/functional-php)
333
+
295
334
## References
296
335
Here links to their articles`/`libraries that help me understood the domain:
0 commit comments