Monads/Maybe monad: Difference between revisions
Content added Content deleted
m (Rewrote a comment/) |
m (→{{header|Python}}: Improve type hints) |
||
Line 1,593: | Line 1,593: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
The <code>Maybe</code> class constructor is effectively the <code>unit</code> function. Note that I've used <code>>></code> as the bind operator. Trying to chain <code>__irshift__</code> (<code>>>=</code>) would be a syntax error. |
|||
In this implementation, a <code>Maybe</code> type's constructor is effectively |
|||
the <code>unit</code> function. Note that I've used <code>>></code> as the bind |
|||
operator. Trying to chain <code>__irshift__</code> (<code>>>=</code>) would be a |
|||
syntax error. |
|||
<syntaxhighlight lang="python"> |
<syntaxhighlight lang="python"> |
||
"""A Maybe monad. Requires Python >= 3.7 for type hints.""" |
|||
from __future__ import annotations |
from __future__ import annotations |
||
from typing import Any |
|||
from typing import Callable |
from typing import Callable |
||
from typing import Generic |
from typing import Generic |
||
Line 1,610: | Line 1,607: | ||
T = TypeVar("T") |
T = TypeVar("T") |
||
U = TypeVar("U") |
|||
Line 1,619: | Line 1,617: | ||
self.value = value |
self.value = value |
||
def __rshift__(self, func: Callable[[Optional[T]], Maybe[ |
def __rshift__(self, func: Callable[[Optional[T]], Maybe[U]]) -> Maybe[U]: |
||
return self.bind(func) |
return self.bind(func) |
||
def bind(self, func: Callable[[Optional[T]], Maybe[ |
def bind(self, func: Callable[[Optional[T]], Maybe[U]]) -> Maybe[U]: |
||
return func(self.value) |
return func(self.value) |
||
Line 1,631: | Line 1,629: | ||
def plus_one(value: Optional[int]) -> Maybe[int]: |
def plus_one(value: Optional[int]) -> Maybe[int]: |
||
if value is not None: |
if value is not None: |
||
return Maybe |
return Maybe(value + 1) |
||
return Maybe |
return Maybe(None) |
||
def currency(value: Optional[int]) -> Maybe[str]: |
def currency(value: Optional[int]) -> Maybe[str]: |
||
if value is not None: |
if value is not None: |
||
return Maybe |
return Maybe(f"${value}.00") |
||
return Maybe |
return Maybe(None) |
||
Line 1,645: | Line 1,643: | ||
for case in test_cases: |
for case in test_cases: |
||
result = Maybe(case) >> plus_one >> currency |
|||
result = m_int >> plus_one >> currency |
|||
# or.. |
# or.. |
||
# result = |
# result = Maybe(case).bind(plus_one).bind(currency) |
||
print(f"{str(case):<4} -> {result}") |
print(f"{str(case):<4} -> {result}") |
||
</syntaxhighlight> |
</syntaxhighlight> |