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">"""A Maybe Monad. Requires Python >= 3.7 for type hints."""
<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[Any]]):
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[Any]]) -> Maybe[Any]:
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[int](value + 1)
return Maybe(value + 1)
return Maybe[int](None)
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[str](f"${value}.00")
return Maybe(f"${value}.00")
return Maybe[str](None)
return Maybe(None)




Line 1,645: Line 1,643:


for case in test_cases:
for case in test_cases:
m_int = Maybe[int](case)
result = Maybe(case) >> plus_one >> currency

result = m_int >> plus_one >> currency
# or..
# or..
# result = m_int.bind(plus_one).bind(currency)
# result = Maybe(case).bind(plus_one).bind(currency)

print(f"{str(case):<4} -> {result}")
print(f"{str(case):<4} -> {result}")
</syntaxhighlight>
</syntaxhighlight>