Created
July 26, 2021 10:11
-
-
Save internetimagery/d00758e48b8aff94d96034b3acebe29e to your computer and use it in GitHub Desktop.
Rough do notation decorator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import inspect | |
| class Monad: | |
| def __init__(self, val): | |
| self.val = val | |
| def bind(self, func): | |
| return func(self.val) | |
| def do(func): | |
| if not inspect.isgeneratorfunction(func): | |
| raise TypeError("not a generator") | |
| def wrapper(*args, **kwargs): | |
| loop = func(*args, **kwargs) | |
| def step(val): | |
| try: | |
| monad = loop.send(val) | |
| except StopIteration as stopper: | |
| return stopper.value | |
| else: | |
| return monad.bind(step) | |
| try: | |
| monad = next(loop) | |
| except StopIteration: | |
| raise RuntimeError("yield must be called at least once") | |
| else: | |
| return monad.bind(step) | |
| return wrapper | |
| def get_first_name(): | |
| return Monad("firstName") | |
| def get_last_name(): | |
| return Monad("lastName") | |
| def get_full_name(first, last): | |
| return Monad(f"{first} {last}") | |
| def get_name_nested(): | |
| return get_first_name().bind( | |
| lambda first: get_last_name().bind( | |
| lambda last: get_full_name(first, last) | |
| ) | |
| ) | |
| @do | |
| def get_name(): | |
| first = yield get_first_name() | |
| last = yield get_last_name() | |
| return get_full_name(first, last) | |
| assert get_name_nested().val == get_name().val == "firstName lastName" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment