Skip to content

Instantly share code, notes, and snippets.

@bedekelly
Created September 18, 2019 10:02
Show Gist options
  • Save bedekelly/decd5c6da32471a8a99d34aa8279b78c to your computer and use it in GitHub Desktop.
Save bedekelly/decd5c6da32471a8a99d34aa8279b78c to your computer and use it in GitHub Desktop.
Do Notation using Python's Yield Keyword
from functools import wraps
def do(f):
def partial_run(f, args, kwargs, values_so_far=()):
# First, create a NEW instance of the coroutine.
coroutine = f(*args, **kwargs)
# Advance the coroutine to the first yield point.
yielded_monad = next(coroutine)
# For each value so far, send it into the coroutine.
for v in values_so_far:
try:
yielded_monad = coroutine.send(v)
except StopIteration as ret:
# This means we've reached the end of the function;
# lift the return value back into the monad.
return yielded_monad.point(ret.value)
def continue_with_value(value):
"""Continue the coroutine execution, pre-filling a given value."""
return partial_run(f, args, kwargs, (*values_so_far, value))
return yielded_monad >> continue_with_value
@wraps
def wrapped(*args, **kwargs):
return partial_run(f, args, kwargs)
return wrapped
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment