diff --git a/src/Monad.php b/src/Monad.php new file mode 100644 index 0000000..dde005f --- /dev/null +++ b/src/Monad.php @@ -0,0 +1,27 @@ + $f + * @return static + */ + public function bind(Closure $f): self; + + /** + * @template TValue + * @param TValue $value + * @return static + */ + public static function unit(mixed $value): self; +} diff --git a/src/Option.php b/src/Option.php new file mode 100644 index 0000000..47276f9 --- /dev/null +++ b/src/Option.php @@ -0,0 +1,24 @@ + + */ +abstract class Option implements Monad +{ + /** + * @template TValue + * @param TValue $value + * @return Option + */ + public static function unit(mixed $value): self + { + return new Some($value); + } +} diff --git a/src/Option/None.php b/src/Option/None.php new file mode 100644 index 0000000..1228410 --- /dev/null +++ b/src/Option/None.php @@ -0,0 +1,48 @@ + + */ +final class None extends Option +{ + /** + * @param T $value + */ + public function __construct(protected mixed $value) + { + } + + /** + * @template T2 + * @param Closure(T): static $f + * @return static + */ + #[Override] + public function bind(Closure $f): self + { + /** @var T2 */ + $v = null; + + return self::unit($v); + } + + /** + * @template TValue + * @param TValue $value + * @return None + */ + #[Override] + public static function unit(mixed $value): self + { + return new self($value); + } +} diff --git a/src/Option/Some.php b/src/Option/Some.php new file mode 100644 index 0000000..1e760ca --- /dev/null +++ b/src/Option/Some.php @@ -0,0 +1,33 @@ + + */ +final class Some extends Option +{ + /** + * @param T $value + */ + public function __construct(protected mixed $value) + { + } + + /** + * @param Closure(T): static $f + * @return static + */ + #[Override] + public function bind(Closure $f): self + { + return $f($this->value); + } +}