widmogrod/php-functional

View on GitHub
src/Monad/IO/errors.php

Summary

Maintainability
A
0 mins
Test Coverage
F
0%
<?php

declare(strict_types=1);

namespace Widmogrod\Monad\IO;

use Widmogrod\Functional as f;
use Widmogrod\Monad as M;
use Widmogrod\Monad\Either as E;

const userError = 'Widmogrod\Monad\IO\userError';

/**
 * userError :: String -> IOError
 *
 * @param string $error
 *
 * @return IOError
 */
function userError($error)
{
    return new IOError($error);
}

const throwIO = 'Widmogrod\Monad\IO\throwIO';

/**
 * A variant of throw that can only be used within the IO monad.
 *
 * throwIO :: Exception e -> IO a
 *
 * @param \Exception $e
 *
 * @return M\IO
 */
function throwIO(\Exception $e)
{
    return M\IO::of(function () use ($e) {
        throw $e;
    });
}

const tryCatch = 'Widmogrod\Monad\IO\tryCatch';

/**
 * tryCatch :: Exception e => IO a -> (e -> IO a) -> IO a
 *
 * @param M\IO     $io
 * @param callable $catchFunction
 *
 * @return M\IO|\Closure
 */
function tryCatch(?M\IO $io = null, ?callable $catchFunction = null)
{
    return f\curryN(2, function (M\IO $io, callable $catchFunction) {
        return M\IO::of(function () use ($io, $catchFunction) {
            try {
                return $io->run();
            } catch (\Exception $e) {
                return $catchFunction($e);
            }
        });
    })(...func_get_args());
}

const tryEither = 'Widmogrod\Monad\IO\tryEither';

/**
 * tryEither :: Exception e => IO a -> IO (Either e a)
 *
 * @param M\IO $io
 *
 * @return M\IO
 */
function tryEither(M\IO $io)
{
    return tryCatch(
        f\bind(E\right, $io),
        E\left
    );
}

/**
 * tryMaybe :: IO a -> IO (Maybe a)
 *
 * @param M\IO $io
 *
 * @return M\IO
 */
function tryMaybe(M\IO $io)
{
    return tryCatch(
        f\bind(M\Maybe\just, $io),
        M\Maybe\nothing
    );
}