Monads/List monad: Difference between revisions
Content added Content deleted
(A Python implementation) |
|||
Line 619: | Line 619: | ||
<pre> |
<pre> |
||
{3,4,5} -> {8,10,12} |
{3,4,5} -> {8,10,12} |
||
</pre> |
|||
=={{header|Python}}== |
|||
<lang python>"""A List Monad. Requires Python >= 3.7 for type hints.""" |
|||
from __future__ import annotations |
|||
from itertools import chain |
|||
from typing import Any |
|||
from typing import Callable |
|||
from typing import Iterable |
|||
from typing import List |
|||
from typing import TypeVar |
|||
T = TypeVar("T") |
|||
class MList(List[T]): |
|||
@classmethod |
|||
def unit(cls, value: Iterable[T]) -> MList[T]: |
|||
return cls(value) |
|||
def bind(self, func: Callable[[T], MList[Any]]) -> MList[Any]: |
|||
return MList(chain.from_iterable(map(func, self))) |
|||
def __rshift__(self, func: Callable[[T], MList[Any]]) -> MList[Any]: |
|||
return self.bind(func) |
|||
if __name__ == "__main__": |
|||
# Chained int and string functions |
|||
print( |
|||
MList([1, 99, 4]) |
|||
.bind(lambda val: MList([val + 1])) |
|||
.bind(lambda val: MList([f"${val}.00"])) |
|||
) |
|||
# Same, but using `>>` as the bind operator. |
|||
print( |
|||
MList([1, 99, 4]) |
|||
>> (lambda val: MList([val + 1])) |
|||
>> (lambda val: MList([f"${val}.00"])) |
|||
) |
|||
# Cartesian product of [1..5] and [6..10] |
|||
print( |
|||
MList(range(1, 6)).bind( |
|||
lambda x: MList(range(6, 11)).bind(lambda y: MList([(x, y)])) |
|||
) |
|||
) |
|||
# Pythagorean triples with elements between 1 and 25 |
|||
print( |
|||
MList(range(1, 26)).bind( |
|||
lambda x: MList(range(x + 1, 26)).bind( |
|||
lambda y: MList(range(y + 1, 26)).bind( |
|||
lambda z: MList([(x, y, z)]) |
|||
if x * x + y * y == z * z |
|||
else MList([]) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
['$2.00', '$100.00', '$5.00'] |
|||
['$2.00', '$100.00', '$5.00'] |
|||
[(1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (2, 6), (2, 7), (2, 8), (2, 9), (2, 10), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (4, 6), (4, 7), (4, 8), (4, 9), (4, 10), (5, 6), (5, 7), (5, 8), (5, 9), (5, 10)] |
|||
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (7, 24, 25), (8, 15, 17), (9, 12, 15), (12, 16, 20), (15, 20, 25)] |
|||
</pre> |
</pre> |
||