Skip to content

Commit f9b92f2

Browse files
author
Jaco Labuschagne
committed
add IOMonadOps
1 parent fe661e8 commit f9b92f2

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

src/IOMonadOps.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Zodimo\BaseReturn;
6+
7+
class IOMonadOps
8+
{
9+
/**
10+
* @template VALUE
11+
* @template ERR
12+
*
13+
* @param array<IOMonad<VALUE,ERR>> $values
14+
*
15+
* @return IOMonad<array<VALUE>, ERR>
16+
*/
17+
public static function sequence(array $values): IOMonad
18+
{
19+
// sequence :: Monad m => Either a (m a0) -> m (Either a a0)
20+
// list of values or first error
21+
$output = [];
22+
foreach ($values as $value) {
23+
/**
24+
* @var IOMonad<VALUE,ERR> $value
25+
*/
26+
if ($value->isFailure()) {
27+
return $value;
28+
}
29+
// @phpstan-ignore method.void
30+
$output[] = $value->unwrapSuccess(function () {});
31+
}
32+
33+
// @phpstan-ignore return.type
34+
return IOMonad::pure($output);
35+
}
36+
}

tests/Unit/IOMonadOpsTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Zodimo\BaseReturn\Tests\Unit;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Zodimo\BaseReturn\IOMonad;
9+
use Zodimo\BaseReturn\IOMonadOps;
10+
use Zodimo\BaseReturnTest\MockClosureTrait;
11+
12+
/**
13+
* @internal
14+
*
15+
* @coversNothing
16+
*/
17+
class IOMonadOpsTest extends TestCase
18+
{
19+
use MockClosureTrait;
20+
21+
public function testSequenceEmptyList(): void
22+
{
23+
// @phpstan-ignore argument.templateType, argument.templateType
24+
$this->assertEquals([], IOMonadOps::sequence([])->unwrapSuccess($this->createClosureNotCalled()));
25+
}
26+
27+
public function testSequenceValidList(): void
28+
{
29+
$input = [
30+
IOMonad::pure(1),
31+
IOMonad::pure(2),
32+
IOMonad::pure(3),
33+
];
34+
35+
$this->assertEquals([1, 2, 3], IOMonadOps::sequence($input)->unwrapSuccess($this->createClosureNotCalled()));
36+
}
37+
38+
public function testSequenceReturnFirstErrorInList(): void
39+
{
40+
$error = new \RuntimeException('error');
41+
$input = [
42+
IOMonad::pure(1),
43+
IOMonad::fail($error),
44+
IOMonad::pure(new \InvalidArgumentException('error')),
45+
];
46+
47+
// @phpstan-ignore argument.type
48+
$this->assertSame($error, IOMonadOps::sequence($input)->unwrapFailure($this->createClosureNotCalled()));
49+
}
50+
}

0 commit comments

Comments
 (0)