PHP code example of gosuperscript / monads

1. Go to this page and download the library: Download gosuperscript/monads library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

gosuperscript / monads example snippets


use function Superscript\Monads\Option\{Some, None};

// Create an Option
$some = Some(42);
$none = None();

// Check if value exists
$some->isSome(); // true
$none->isNone(); // true

// Transform the value
$doubled = Some(21)->map(fn($x) => $x * 2); // Some(42)
$empty = None()->map(fn($x) => $x * 2);    // None

// Provide default values
Some(42)->unwrapOr(0);  // 42
None()->unwrapOr(0);    // 0

// Chain operations
Some(10)
    ->filter(fn($x) => $x > 5)
    ->map(fn($x) => $x * 2)
    ->unwrapOr(0); // 20

// Convert to Result
Some(42)->okOr("error");  // Ok(42)
None()->okOr("error");    // Err("error")

use function Superscript\Monads\Result\{Ok, Err, attempt};

// Create Results
$ok = Ok(42);
$err = Err("something went wrong");

// Check the result
$ok->isOk();   // true
$err->isErr(); // true

// Transform success values
$doubled = Ok(21)->map(fn($x) => $x * 2); // Ok(42)
$stillErr = Err("error")->map(fn($x) => $x * 2); // Err("error")

// Transform error values
$recovered = Err("error")->mapErr(fn($e) => "recovered"); // Err("recovered")

// Handle both cases
$result = Ok(10)->match(
    err: fn($e) => "Error: $e",
    ok: fn($x) => "Success: $x"
); // "Success: 10"

// Chain operations
Ok(10)
    ->map(fn($x) => $x * 2)
    ->andThen(fn($x) => $x > 15 ? Ok($x) : Err("too small"))
    ->unwrapOr(0); // 20

// Convert to Option
Ok(42)->ok();   // Some(42)
Err("e")->ok(); // None()

// Safely execute code that might throw
$result = attempt(fn() => json_decode($json, flags: JSON_THROW_ON_ERROR));
// Returns: Result<mixed, Throwable>

use Superscript\Monads\Lazy\Lazy;

// Create a lazy computation
$lazy = Lazy::of(fn() => expensiveComputation());

// The computation hasn't run yet...

// Evaluate when needed (memoized)
$result = $lazy->evaluate(); // Runs the computation
$cached = $lazy->evaluate(); // Returns cached result

// Practical example: lazy database query
$users = Lazy::of(fn() => DB::query("SELECT * FROM users"));

if ($needUsers) {
    $data = $users->evaluate(); // Query runs only if needed
}

use Superscript\Monads\Writer\Writer;
use function Superscript\Monads\Writer\Writer;

// Create a Writer with an array-based log
$writer = Writer(42, ['initial value']);

// Access value and log
$writer->value(); // 42
$writer->log();   // ['initial value']
$writer->run();   // [42, ['initial value']]

// Transform the value (log unchanged)
Writer(21)->map(fn($x) => $x * 2); // Writer(42, [])

// Chain computations that produce their own logs
Writer(10, ['start'])
    ->andThen(fn($x) => Writer($x * 2, ['doubled']))
    ->andThen(fn($x) => Writer($x + 1, ['incremented']));
// value: 21, log: ['start', 'doubled', 'incremented']

// Append to the log without changing the value
Writer(42)->tell(['something happened']);
// value: 42, log: ['something happened']

// Use a custom log type with Writer::of()
$writer = Writer::of('hello', '', fn(string $a, string $b): string => $a . $b)
    ->tell(' world')
    ->map(fn($v) => strtoupper($v));
// value: 'HELLO', log: ' world'

use function Superscript\Monads\Option\{Some, None};
use function Superscript\Monads\Result\{Ok, Err};

// Collect Options - returns first None or Some(array)
Option::collect([Some(1), Some(2), Some(3)]); // Some([1, 2, 3])
Option::collect([Some(1), None(), Some(3)]);  // None()

// Collect Results - returns first Err or Ok(array)
Result::collect([Ok(1), Ok(2), Ok(3)]);     // Ok([1, 2, 3])
Result::collect([Ok(1), Err("e"), Ok(3)]);  // Err("e")

use Superscript\Monads\Option\Option;

function getUser(int $id): Option {
    $user = DB::find('users', $id);
    return Option::from($user); // Returns None if null
}

$username = getUser(123)
    ->map(fn($user) => $user->name)
    ->unwrapOr('Guest');

use function Superscript\Monads\Result\{Ok, Err, attempt};

function divide(int $a, int $b): Result {
    return $b === 0 
        ? Err("Division by zero")
        : Ok($a / $b);
}

$result = divide(10, 2)
    ->map(fn($x) => $x * 2)
    ->unwrapOr(0); // 10

$error = divide(10, 0)
    ->map(fn($x) => $x * 2)
    ->unwrapOr(0); // 0

use function Superscript\Monads\Writer\Writer;

function addTax(float $price): Writer {
    $taxed = $price * 1.2;
    return Writer($taxed, [sprintf('Tax: %.2f -> %.2f', $price, $taxed)]);
}

function applyDiscount(float $price): Writer {
    $discounted = $price * 0.9;
    return Writer($discounted, [sprintf('Discount: %.2f -> %.2f', $price, $discounted)]);
}

$result = Writer(100.0, ['Starting price: 100.00'])
    ->andThen(fn($p) => addTax($p))
    ->andThen(fn($p) => applyDiscount($p));

$result->value(); // 108.0
$result->log();   // ['Starting price: 100.00', 'Tax: 100.00 -> 120.00', 'Discount: 120.00 -> 108.00']

use function Superscript\Monads\Result\{Ok, Err};

function processData(array $data): Result {
    return Ok($data)
        ->andThen(fn($d) => validateData($d))
        ->andThen(fn($d) => transformData($d))
        ->andThen(fn($d) => saveData($d));
}

$result = processData($input)->match(
    err: fn($e) => response()->json(['error' => $e], 400),
    ok: fn($d) => response()->json(['data' => $d], 200)
);

use Superscript\Monads\Result\Testing\ComparesResults;
use Superscript\Monads\Option\Testing\ComparesOptions;

class MyTest extends TestCase {
    use ComparesResults;
    use ComparesOptions;
    
    public function test_example() {
        // Custom assertions
        $this->assertOk(Ok(42));
        $this->assertErr(Err("error"));
        $this->assertSome(Some(42));
        $this->assertNone(None());
        
        // PHPUnit constraints
        $this->assertThat(Ok(42), $this->isOk());
        $this->assertThat(Err("e"), $this->isErr());
    }
}