Monads/Maybe monad: Difference between revisions
Content added Content deleted
(A Python implementation) |
|||
Line 1,072: | Line 1,072: | ||
3 -> 19 |
3 -> 19 |
||
"none" -> "none" |
"none" -> "none" |
||
</pre> |
|||
=={{header|Python}}== |
|||
In this implementation, a <code>Maybe</code> type's constructor is effectively |
|||
the <code>unit</code> function. I've stopped short of implementing |
|||
<code>of</code>, <code>get</code>, <code>isPresent</code>, etc., methods that |
|||
might be familiar to those who've used the <code>Optional</code> class in Java. |
|||
Note that I've used <code>>></code> as the bind operator. Trying to chain |
|||
<code>__irshift__</code> (<code>>>=</code>) would be a syntax error. |
|||
<lang python>"""A Maybe Monad. Requires Python >= 3.7 for type hints.""" |
|||
from __future__ import annotations |
|||
from typing import Any |
|||
from typing import Callable |
|||
from typing import Generic |
|||
from typing import Optional |
|||
from typing import TypeVar |
|||
from typing import TYPE_CHECKING |
|||
T = TypeVar("T") |
|||
if TYPE_CHECKING: |
|||
F = Callable[[Optional[T]], Maybe[Any]] |
|||
class Maybe(Generic[T]): |
|||
def __init__(self, value: Optional[T]): |
|||
self.value = value |
|||
def __rshift__(self, func: F): |
|||
return self.bind(func) |
|||
def bind(self, func: F) -> Maybe[Any]: |
|||
return func(self.value) |
|||
def __str__(self): |
|||
return f"{self.__class__.__name__}({self.value!r})" |
|||
def plus_one(value: Optional[int]) -> Maybe[int]: |
|||
if value is not None: |
|||
return Maybe[int](value + 1) |
|||
return Maybe[int](None) |
|||
def currency(value: Optional[int]) -> Maybe[str]: |
|||
if value is not None: |
|||
return Maybe[str](f"${value}.00") |
|||
return Maybe[str](None) |
|||
if __name__ == "__main__": |
|||
test_cases = [1, 99, None, 4] |
|||
for case in test_cases: |
|||
m_int = Maybe[int](case) |
|||
result = m_int >> plus_one >> currency |
|||
# or.. |
|||
# result = m_int.bind(plus_one).bind(currency) |
|||
print(f"{str(case):<4} -> {result}") |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
1 -> MaybeStr('$2.00') |
|||
99 -> MaybeStr('$100.00') |
|||
None -> MaybeStr(None) |
|||
4 -> MaybeStr('$5.00') |
|||
</pre> |
</pre> |
||