Skip to content

Instantly share code, notes, and snippets.

@internetimagery
Created July 26, 2021 10:11
Show Gist options
  • Select an option

  • Save internetimagery/d00758e48b8aff94d96034b3acebe29e to your computer and use it in GitHub Desktop.

Select an option

Save internetimagery/d00758e48b8aff94d96034b3acebe29e to your computer and use it in GitHub Desktop.
Rough do notation decorator
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