1: <?php
2:
3: namespace Chromabits\Nucleus\Control;
4:
5: use Chromabits\Nucleus\Data\Interfaces\FunctorInterface;
6: use Chromabits\Nucleus\Data\Interfaces\MonoidInterface;
7: use Chromabits\Nucleus\Data\Interfaces\SemigroupInterface;
8: use Chromabits\Nucleus\Exceptions\MindTheGapException;
9: use Chromabits\Nucleus\Meditation\Exceptions\InvalidArgumentException;
10: use Closure;
11:
12: /**
13: * Class MaybeMonad
14: *
15: * @author Eduardo Trujillo <ed@chromabits.com>
16: * @package Chromabits\Nucleus\Monads
17: */
18: abstract class Maybe extends Monad implements FunctorInterface, MonoidInterface
19: {
20: /**
21: * Extracts the element out of a Just.
22: *
23: * @param Maybe $maybe
24: *
25: * @return mixed
26: * @throws InvalidArgumentException
27: */
28: public static function fromJust(Maybe $maybe)
29: {
30: if ($maybe->isNothing()) {
31: throw new InvalidArgumentException();
32: }
33:
34: return $maybe->value;
35: }
36:
37: /**
38: * Returns whether or not the contained value is Nothing.
39: *
40: * @return bool
41: */
42: abstract public function isNothing();
43:
44: /**
45: * The fromMaybe function takes a default value and and Maybe value.
46: * If the Maybe is Nothing, it returns the default values; otherwise,
47: * it returns the value contained in the Maybe.
48: *
49: * @param mixed $default
50: * @param Maybe $maybe
51: *
52: * @return mixed
53: */
54: public static function fromMaybe($default, Maybe $maybe)
55: {
56: if ($maybe->isNothing()) {
57: return $default;
58: }
59:
60: return $maybe->value;
61: }
62:
63: /**
64: * @inheritDoc
65: */
66: public static function zero()
67: {
68: return static::nothing();
69: }
70:
71: /**
72: * >>=
73: *
74: * @param callable|Closure $closure
75: *
76: * @return Maybe
77: */
78: public function bind(callable $closure)
79: {
80: if ($this->isJust()) {
81: return static::of($closure($this->value));
82: }
83:
84: return static::nothing();
85: }
86:
87: /**
88: * Returns whether or not the contained value is in the form Just _.
89: *
90: * @return bool
91: */
92: abstract public function isJust();
93:
94: /**
95: * @inheritDoc
96: */
97: public static function of($value)
98: {
99: if ($value instanceof static) {
100: return $value;
101: }
102:
103: return static::just($value);
104: }
105:
106: /**
107: * Just constructor.
108: *
109: * @param mixed $value
110: *
111: * @return Maybe
112: */
113: public static function just($value)
114: {
115: return new Just($value);
116: }
117:
118: /**
119: * Nothing constructor.
120: *
121: * @return Maybe
122: */
123: public static function nothing()
124: {
125: return new Nothing(null);
126: }
127:
128: /**
129: * @inheritDoc
130: */
131: public function append(SemigroupInterface $other)
132: {
133: throw new MindTheGapException();
134: }
135: }
136: