chippyash/Monad

View on GitHub
src/chippyash/Monad/Monad.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
/**
 * Monad
 *
 * @author Ashley Kitson
 * @copyright Ashley Kitson, 2015, UK
 * @license GPL V3+ See LICENSE.md
 */
declare(strict_types=1);
namespace Monad;

/**
 * Abstract Monad
 * You'll need to supply a constructor to set the initial value in your
 * descendant class
 *
 */
abstract class Monad implements Monadic
{
    use CallFunctionAble;
    use FlattenAble;
    use ReturnValueAble;

    /**
     * Bind monad with function.  Function is in form f($value){}
     * You can pass additional parameters in the $args array in which case your
     * function should be in the form f($value, $arg1, ..., $argN)
     *
     * @param \Closure $function
     * @param array $args additional arguments to pass to function
     *
     * @return Monadic
     */
    public function bind(\Closure $function, array $args = []): Monadic
    {
        return $this::create($this->callFunction($function, $this->value, $args));
    }

    /**
     * Static factory creator for the Monad
     *
     * @param $value
     *
     * @return Monadic
     */
    public static function create($value)
    {
        if ($value instanceof Monadic) {
            return $value;
        }

        return new static($value);
    }

    /**
     * Some syntactic sugar
     *
     * Proxy to bind() e.g. $ret = $foo(function($val){return $val * 2;});
     * Proxy to value() e.g. $val = $foo();
     *
     * @see bind()
     * @see value()
     *
     * @return mixed|Monadic
     * @throw BadMethodCallException
     */
    public function __invoke()
    {
        if (func_num_args() == 0) {
            return $this->value();
        }
        if (func_get_arg(0) instanceof \Closure) {
            return call_user_func_array(array($this, 'bind'), func_get_args());
        }

        throw new \BadMethodCallException('Invoke could not match value() or bind()');
    }
}